Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
497ac120ec | ||
|
|
a486016d96 | ||
|
|
cc5f5653ef | ||
|
|
20222c450d | ||
|
|
69049e1345 | ||
|
|
ed6264444f | ||
|
|
86f4fc3394 | ||
|
|
565589fc94 | ||
|
|
4ef92e5abd | ||
|
|
7f8751fa38 | ||
|
|
befcba00b4 | ||
|
|
26e4b637a2 | ||
|
|
75e3bc6f93 | ||
|
|
70bb125076 | ||
|
|
e0a4fc186a | ||
|
|
6a9d30e8ea | ||
|
|
1e6a12eeda | ||
|
|
31912da76f | ||
|
|
fe8896e870 | ||
|
|
c99517572e | ||
|
|
0b7f30a7c4 | ||
|
|
fcfaf043c4 | ||
|
|
0393a330a6 | ||
|
|
2fdb58bc7d | ||
|
|
c758bda1a9 | ||
|
|
88e301e2a2 | ||
|
|
161c664e08 | ||
|
|
a0408ec798 | ||
|
|
480d5586b9 | ||
|
|
7b49018593 | ||
|
|
4b447a9b9d | ||
|
|
443feb2bfa | ||
|
|
8710101a78 | ||
|
|
2c20148e64 | ||
|
|
ffc0e84788 | ||
|
|
2d2004e447 | ||
|
|
4a7cfc113d | ||
|
|
f03ad5a0e9 | ||
|
|
7f5b83f9d8 | ||
|
|
5a8f93e225 | ||
|
|
668b0f6b23 | ||
|
|
fc1eb5a408 | ||
|
|
561c7e22b3 | ||
|
|
ce067d4ff0 | ||
|
|
7361b54255 | ||
|
|
9e2334ca83 | ||
|
|
08d1f1d5e4 | ||
|
|
f3bf4f0096 | ||
|
|
b4094d0a5b | ||
|
|
36122b4ac5 | ||
|
|
dd9aba3adb | ||
|
|
bd40fbae74 | ||
|
|
690cbc49cc | ||
|
|
36b16ddeef | ||
|
|
16b8988fa7 | ||
|
|
40f97b7c35 | ||
|
|
54b3113480 | ||
|
|
7e9140492a | ||
|
|
79c0aed54f | ||
|
|
cb5a74de00 | ||
|
|
31f25f346a | ||
|
|
b3a11125a5 | ||
|
|
71cdc03da5 | ||
|
|
694e73a677 | ||
|
|
5aaacccef9 | ||
|
|
f2bf043900 | ||
|
|
ba251fe407 | ||
|
|
421aa9dc69 | ||
|
|
b4a7f1353b | ||
|
|
30de3c6db5 | ||
|
|
8aafa26238 | ||
|
|
5768391305 | ||
|
|
1d204bacf2 | ||
|
|
4d1d5d48c0 | ||
|
|
5a6321535e | ||
|
|
e077de9f48 | ||
|
|
7586f03998 | ||
|
|
af8c22dcda | ||
|
|
3dce5dc617 | ||
|
|
84b90e1026 | ||
|
|
d507586eed | ||
|
|
57afaedf83 | ||
|
|
48063b9066 | ||
|
|
452d356599 | ||
|
|
25eda8041e | ||
|
|
ae4d5356eb | ||
|
|
3343bb906e | ||
|
|
7b17900160 | ||
|
|
d5f1fe1c7b | ||
|
|
553f73f992 | ||
|
|
c8cedf2e2c | ||
|
|
a751817847 | ||
|
|
d1ef12db8d | ||
|
|
43d73edf29 | ||
|
|
5a0b8c376c | ||
|
|
9743fd460e | ||
|
|
f70f92a176 | ||
|
|
1a4175446c | ||
|
|
ed6dfab4c1 | ||
|
|
6a6e1105c0 | ||
|
|
1677fe254b | ||
|
|
02efe708c2 | ||
|
|
7dc834f506 | ||
|
|
57c4958ff2 | ||
|
|
03e59a8cce | ||
|
|
f3d18f09a0 | ||
|
|
c1dbd984e6 | ||
|
|
e4f227221d | ||
|
|
34139974aa | ||
|
|
408b2422e6 | ||
|
|
b59cb9e200 | ||
|
|
bd5cb65d0f | ||
|
|
4cfe487af0 | ||
|
|
4da2e39e32 | ||
|
|
5ff11a32c9 | ||
|
|
01a7ec916e | ||
|
|
dd94a7d613 | ||
|
|
089b88c62d | ||
|
|
c9ca75e2e8 | ||
|
|
091f6a3ed0 | ||
|
|
d6c9fb1025 | ||
|
|
88abd72a41 | ||
|
|
1137e851ce | ||
|
|
b8c1500aad | ||
|
|
bfd0d90abc | ||
|
|
dba01e1826 | ||
|
|
2189c76edd | ||
|
|
6f8c9d66db | ||
|
|
9408ce10c7 | ||
|
|
9895c3c304 | ||
|
|
0ab3b77db8 | ||
|
|
d13e7e7a0a | ||
|
|
9c6e03f4a8 | ||
|
|
2a4dfe010e | ||
|
|
f42a916c25 | ||
|
|
772b810fa8 | ||
|
|
4d4d10d5c2 | ||
|
|
0e4c7dbe64 | ||
|
|
e96b544a75 | ||
|
|
375204c379 | ||
|
|
d76c03af4f | ||
|
|
200a6586ba | ||
|
|
a01ca79a82 | ||
|
|
c91baf7c83 | ||
|
|
5062de8ddf | ||
|
|
f0f1ecb2df | ||
|
|
2eb6ef6f03 | ||
|
|
f7c0805161 | ||
|
|
4e18e3c8a0 | ||
|
|
59f31caf26 | ||
|
|
f24956c58d | ||
|
|
9019317e5c | ||
|
|
2a0227c1de | ||
|
|
f70db42b91 | ||
|
|
9cd87742f0 | ||
|
|
5dcb93ca5d | ||
|
|
256d62b29b | ||
|
|
595ea8e2d3 | ||
|
|
9ca46b9d35 | ||
|
|
d3e733aa3e | ||
|
|
a011768d2d | ||
|
|
4b45b5d716 | ||
|
|
ebe9681c12 | ||
|
|
51c85e4cd5 | ||
|
|
2e171dfbee | ||
|
|
a6a3917986 | ||
|
|
21f2448213 | ||
|
|
e7a1d0488b | ||
|
|
22b8e0edb4 | ||
|
|
d062a38e8f | ||
|
|
affa59130f | ||
|
|
3c816567bc | ||
|
|
7c2e24bbc4 | ||
|
|
e92e48ffde | ||
|
|
4ce7777b86 | ||
|
|
bc130ad867 | ||
|
|
867b6a6ac7 | ||
|
|
e585fd084c | ||
|
|
b47bb4a771 | ||
|
|
9cff71fed3 | ||
|
|
e76040e416 | ||
|
|
1facf50621 | ||
|
|
57f3cc8bc0 | ||
|
|
1ab3fe1c4a | ||
|
|
10cff632fd | ||
|
|
4105687c0a | ||
|
|
8fe6565527 | ||
|
|
69b018022d | ||
|
|
467cb2e589 | ||
|
|
f13d8c1e22 | ||
|
|
e230d55b82 | ||
|
|
46fcdb4bb2 | ||
|
|
429212ef23 | ||
|
|
4ea0ea6a7a | ||
|
|
2e3ce83605 | ||
|
|
fda908dd0d | ||
|
|
cad77e2b10 | ||
|
|
3542a7c24d | ||
|
|
0d6d161e23 | ||
|
|
89a2e0086b | ||
|
|
cd443faf61 | ||
|
|
bfc56b02a8 | ||
|
|
25bafc6bf1 | ||
|
|
6387580626 | ||
|
|
09b8aa65fc | ||
|
|
6c15193f32 | ||
|
|
4442e29b66 | ||
|
|
b6f96d9f4d | ||
|
|
36b66100f9 | ||
|
|
49d8143cc6 | ||
|
|
fc279fecaf | ||
|
|
bd307daa57 | ||
|
|
7a72f44722 | ||
|
|
8e63fc6946 | ||
|
|
3a65f8dc16 | ||
|
|
d624352a0b | ||
|
|
3fb597a774 | ||
|
|
85e46bc524 | ||
|
|
d3790878b3 | ||
|
|
e648e50f1b | ||
|
|
cb6cede0b6 | ||
|
|
a0157ddc2a | ||
|
|
8f595fbc7b | ||
|
|
2e3b22c5fa | ||
|
|
42b968372b | ||
|
|
415e7b492f | ||
|
|
2ea8e46723 | ||
|
|
977c6c6dde | ||
|
|
1e5db9dc6c | ||
|
|
252dc10e61 | ||
|
|
f9e2315ba1 | ||
|
|
0eca588280 | ||
|
|
33523bbfb9 | ||
|
|
110f23bdf1 | ||
|
|
50a5cb23f5 | ||
|
|
30e72db5ea | ||
|
|
c4c64c8fe8 | ||
|
|
df39350d7d | ||
|
|
5daacd3ed4 | ||
|
|
0f7f64fb2f | ||
|
|
b09a1fdcb7 | ||
|
|
e5d45dee3a | ||
|
|
f3270e19df | ||
|
|
1b9ad41c87 | ||
|
|
8c3365ef24 | ||
|
|
db5cbffb70 | ||
|
|
c6586f0eed | ||
|
|
f40bdc8ed9 | ||
|
|
683ac4e118 | ||
|
|
88c9abb78e | ||
|
|
1729a2f734 | ||
|
|
e5ad8bbb70 | ||
|
|
7f6acbfdbc | ||
|
|
2e070529e0 | ||
|
|
f4b31e5f0a | ||
|
|
f7f093a464 | ||
|
|
95cc340de5 | ||
|
|
51a003c816 | ||
|
|
977152139f | ||
|
|
c6798dbcd5 | ||
|
|
78833df95e | ||
|
|
099d941d2e | ||
|
|
ea58f378a9 | ||
|
|
4060884909 | ||
|
|
d9277c11d2 | ||
|
|
bcbc90820a | ||
|
|
e9caa95673 | ||
|
|
9cd6703b05 | ||
|
|
4233bd7771 | ||
|
|
0e2db441f2 | ||
|
|
571b101ea4 | ||
|
|
0b9dca61ab | ||
|
|
d8fa76d076 | ||
|
|
6116eef513 | ||
|
|
fabe987f2c | ||
|
|
af20880f37 | ||
|
|
44eeab0d4b | ||
|
|
b331900158 | ||
|
|
d74380404c | ||
|
|
3833a9cd6b | ||
|
|
74fdd943c9 | ||
|
|
ad5b772502 | ||
|
|
9bc941aa31 | ||
|
|
705df43047 | ||
|
|
b31e3bb710 | ||
|
|
4082d0a368 | ||
|
|
ce85286cdf | ||
|
|
415cf1a777 | ||
|
|
f249919ec8 | ||
|
|
054c9787d3 | ||
|
|
c1e88e2b5a | ||
|
|
f5efeb16c4 | ||
|
|
59afae7bca | ||
|
|
92c6339064 | ||
|
|
582ae233f2 | ||
|
|
3c3016a211 | ||
|
|
e24e1d9d3c | ||
|
|
85fb564be7 | ||
|
|
18f7db9eee | ||
|
|
ea0770fd11 | ||
|
|
9c28fab3f9 | ||
|
|
bac332a8c4 | ||
|
|
86d2542bd9 | ||
|
|
5f63ec884f | ||
|
|
0f87b33354 | ||
|
|
c7dc99a12f | ||
|
|
05c3c3f8f3 | ||
|
|
2437a43471 | ||
|
|
16cd812ba0 | ||
|
|
c036128720 | ||
|
|
645db15848 | ||
|
|
21e142ffc3 | ||
|
|
23a6b3db72 | ||
|
|
b87d109625 | ||
|
|
651bd295b9 | ||
|
|
01607e92b9 | ||
|
|
f40d54adbb | ||
|
|
60fb387495 | ||
|
|
a7df18723c | ||
|
|
4e39cc937a | ||
|
|
fe513c17ab | ||
|
|
f7fb88ed3d | ||
|
|
b3247c7cbe | ||
|
|
d490dc0a8b | ||
|
|
97e79c23f6 | ||
|
|
7803a29875 | ||
|
|
08093beed1 | ||
|
|
ae46ae89bc | ||
|
|
f7977dca39 | ||
|
|
0b344f3e08 | ||
|
|
6058154eca | ||
|
|
941016f04b | ||
|
|
7a15898087 | ||
|
|
6b4effa90f | ||
|
|
77d56e4a4c | ||
|
|
c4dd622e7b | ||
|
|
9f24535142 | ||
|
|
a45161fcb8 | ||
|
|
4379763a73 | ||
|
|
a25b376dfd | ||
|
|
fb429f6777 | ||
|
|
ae33227c3a | ||
|
|
2fedc61d1e | ||
|
|
6988a36dd1 | ||
|
|
60e1124970 | ||
|
|
a007684006 | ||
|
|
090a709522 | ||
|
|
9e06655214 | ||
|
|
3651825e79 | ||
|
|
dcf3160b58 | ||
|
|
fd014f42cd | ||
|
|
a760f2f7fc | ||
|
|
262c114b7d | ||
|
|
c90bdd83bb | ||
|
|
fdb2d37b12 | ||
|
|
7951837ecf | ||
|
|
d2e112a672 | ||
|
|
90e86077ba | ||
|
|
f69dfcdefe | ||
|
|
5cff7c4e72 | ||
|
|
0eaa833cdf | ||
|
|
db015d925e | ||
|
|
69fd47601e | ||
|
|
17521574f0 | ||
|
|
56650a76ae | ||
|
|
984a98e792 | ||
|
|
49eb0cf202 | ||
|
|
8e24a6b036 | ||
|
|
d07bf6d699 | ||
|
|
877d12c676 | ||
|
|
ca629f625a | ||
|
|
087dd9a4b6 | ||
|
|
d9a967c072 | ||
|
|
6d522c82c3 | ||
|
|
867af98083 | ||
|
|
1be058d831 | ||
|
|
71bc044ae5 | ||
|
|
d660c50ade | ||
|
|
3fd733d903 | ||
|
|
7703b2361d | ||
|
|
68fdb9ebc6 | ||
|
|
b6513343be | ||
|
|
cc95ff1c55 | ||
|
|
c954ee0fde | ||
|
|
1ada5e5d18 | ||
|
|
f5244c3d93 | ||
|
|
1f17776cd4 | ||
|
|
ebd4f36f94 | ||
|
|
dbb9b5f254 | ||
|
|
4301472cb2 | ||
|
|
15e7954321 | ||
|
|
32d1de08e9 | ||
|
|
ea88663dce | ||
|
|
97aecaf890 | ||
|
|
b16688e1b7 | ||
|
|
5ac856251b | ||
|
|
62a9aacd85 | ||
|
|
dff0b55a8c | ||
|
|
3b21c75b13 | ||
|
|
2c7cc4b8e5 | ||
|
|
bcf8c0e35c | ||
|
|
11d2936fca | ||
|
|
5e84429e24 | ||
|
|
48c88b2d7e | ||
|
|
e5185c0b77 | ||
|
|
15773d3aba | ||
|
|
b577837446 | ||
|
|
324e234b2a | ||
|
|
d40fefb0ea | ||
|
|
7e05568549 | ||
|
|
0249a52d1c | ||
|
|
5df1c5b09b | ||
|
|
953ec8fe31 | ||
|
|
6054afebdc | ||
|
|
04f356e119 | ||
|
|
a6ebefbb30 | ||
|
|
9a1edbe1fa | ||
|
|
c46d74be54 | ||
|
|
72e949586a | ||
|
|
68dacad741 | ||
|
|
7e6505ca73 | ||
|
|
362d83f504 | ||
|
|
e4879736b7 | ||
|
|
68fe6628c7 | ||
|
|
f39ef569be | ||
|
|
42c199376a | ||
|
|
cd6b774a8c | ||
|
|
62598f94f8 | ||
|
|
aa3b46141f | ||
|
|
dcaa2aaeab | ||
|
|
e36f5e47da | ||
|
|
578d7b41b4 | ||
|
|
c4f81ce279 | ||
|
|
02a7dbea85 | ||
|
|
0305d3fe36 | ||
|
|
84fd034197 | ||
|
|
61b48e2048 | ||
|
|
c91f85389c | ||
|
|
f3683355a9 | ||
|
|
a86da886f4 | ||
|
|
7bf8d42eb8 | ||
|
|
88533e29b9 | ||
|
|
8299dcc881 | ||
|
|
0d0c250fea | ||
|
|
eb8d86616b | ||
|
|
1edc90810f | ||
|
|
c011d84a35 | ||
|
|
b97f62ac12 | ||
|
|
200a38bdc0 | ||
|
|
e12c53a90e | ||
|
|
7892916f56 | ||
|
|
5d681beab3 | ||
|
|
a54a2affb3 | ||
|
|
120062bb85 | ||
|
|
a0754d2bd7 | ||
|
|
f4b13a84d4 | ||
|
|
1c98e27e4d | ||
|
|
6067e25df8 | ||
|
|
304c50a247 | ||
|
|
274ad8eac2 | ||
|
|
9946a3fc0e | ||
|
|
622d6db968 | ||
|
|
d756ce0656 | ||
|
|
316e776355 | ||
|
|
f861b7ad99 | ||
|
|
01382e98f3 | ||
|
|
3371442bbc | ||
|
|
a81a804364 | ||
|
|
b24cf5c946 | ||
|
|
3d60213644 | ||
|
|
a23822c9df | ||
|
|
9fa69758f1 | ||
|
|
c892d3f134 | ||
|
|
73271501dc | ||
|
|
a62ea520e7 | ||
|
|
a2a0b3c71e | ||
|
|
51bedbe003 | ||
|
|
7062a3e657 | ||
|
|
209d95d5da | ||
|
|
95ee74ab2b | ||
|
|
9f6b268dce | ||
|
|
96e8ebcc10 | ||
|
|
ca261c7037 | ||
|
|
a95fe13b31 | ||
|
|
c3fe76adf9 | ||
|
|
e9b9d51a6e | ||
|
|
aff66205e9 | ||
|
|
aa0c9d65ae | ||
|
|
423bd2122f | ||
|
|
7533910114 | ||
|
|
0d4d377c22 | ||
|
|
3a576b3ea5 | ||
|
|
27f37744a0 | ||
|
|
012ecad0bb | ||
|
|
49b5d5e961 | ||
|
|
01ca48fe96 | ||
|
|
5abe5045b2 | ||
|
|
8c79a577b9 | ||
|
|
5b18f1016f | ||
|
|
bda58312bb | ||
|
|
eff352a003 | ||
|
|
3109d4ff82 | ||
|
|
c44eda3af6 | ||
|
|
33e8c41c6f | ||
|
|
e0b515ba2b | ||
|
|
c6b6ad41fb | ||
|
|
99576238cd | ||
|
|
db712650ef | ||
|
|
d77e7b07eb | ||
|
|
47b35fad3f | ||
|
|
720105ca92 | ||
|
|
ce656068e3 | ||
|
|
e69ba76e7d | ||
|
|
d1bab213a3 | ||
|
|
016a9341ad | ||
|
|
81f407ad5f | ||
|
|
37ff2f6bdb | ||
|
|
13cf1a9551 | ||
|
|
799aaac449 | ||
|
|
fbe430e4cf | ||
|
|
511746620e | ||
|
|
fed5b648f8 | ||
|
|
1f601743f6 | ||
|
|
db3ccf5da7 | ||
|
|
038898d580 | ||
|
|
dafbc6bc51 | ||
|
|
3d8271e7a1 | ||
|
|
e2ade95219 | ||
|
|
604971a576 | ||
|
|
76173103af | ||
|
|
3fcbc60232 | ||
|
|
835bdb39d0 | ||
|
|
200f09c5d2 | ||
|
|
99a008f122 | ||
|
|
9b71e89ba0 | ||
|
|
9955369cfa | ||
|
|
6ef6ffab66 | ||
|
|
0dd46f0f20 | ||
|
|
cce0d85dd4 | ||
|
|
1ed3eae038 | ||
|
|
2854c24197 | ||
|
|
4b90ddda2a | ||
|
|
552c39e583 | ||
|
|
5176e459b5 | ||
|
|
39515d0600 | ||
|
|
5314949394 | ||
|
|
59e5be749c | ||
|
|
da252a0070 | ||
|
|
b6199e430c | ||
|
|
e260a68c26 | ||
|
|
570cb2deaf | ||
|
|
7a36f03fb5 | ||
|
|
6c3058ba97 | ||
|
|
48a1034c12 | ||
|
|
aaddb50ab9 | ||
|
|
a947586cfe | ||
|
|
f3cfa14a59 | ||
|
|
a2c0a77c53 | ||
|
|
c078f9d5cb | ||
|
|
08eab8a157 | ||
|
|
9c36f234bc | ||
|
|
36b81d0e2a | ||
|
|
4432c14377 | ||
|
|
99e6dd5ca3 | ||
|
|
6327a25aec | ||
|
|
40989de7f5 | ||
|
|
58af44e795 | ||
|
|
4910cc05f8 | ||
|
|
164ee24d16 | ||
|
|
0ffda4ab7c | ||
|
|
4694a6271d | ||
|
|
2f50bc747a | ||
|
|
a13f621a81 | ||
|
|
0cc520cc67 | ||
|
|
c9451c3f2d | ||
|
|
8da53ffda2 | ||
|
|
4319761687 | ||
|
|
a1f3227cd9 | ||
|
|
b07f87c920 | ||
|
|
9c8f23eb64 | ||
|
|
36c6c623de | ||
|
|
e334419e24 | ||
|
|
01240c4f2a | ||
|
|
431a9ce827 | ||
|
|
20ab41c3b4 | ||
|
|
3f4ea27be2 | ||
|
|
5bb5b2f8c8 | ||
|
|
e9bb9e27bb | ||
|
|
ee1dd1fae7 | ||
|
|
738530a960 | ||
|
|
16023b0688 | ||
|
|
bce7b5984f | ||
|
|
4e5d7d391a | ||
|
|
0554a85e01 | ||
|
|
2d232b3c4b | ||
|
|
b2a5462372 | ||
|
|
9d61f51270 | ||
|
|
a0eb7d61cc | ||
|
|
9861b319f4 | ||
|
|
b04e0f10b2 | ||
|
|
e6d089b34b | ||
|
|
9df014e986 | ||
|
|
39b8d2e70d | ||
|
|
59710d2e1a | ||
|
|
712dc9bb34 | ||
|
|
5c338d53ae | ||
|
|
ec3eb387e5 | ||
|
|
722cf58486 | ||
|
|
17e5347d55 | ||
|
|
2e828dfde3 | ||
|
|
1b035bcde3 | ||
|
|
30981130c9 | ||
|
|
6db8696a36 | ||
|
|
9c83dcafa7 | ||
|
|
1db9ecafef | ||
|
|
aa624e2c60 | ||
|
|
bde7e3e8aa | ||
|
|
b2b3e1b153 | ||
|
|
76b3d09320 | ||
|
|
899dcddd2e | ||
|
|
9edae7e1b8 | ||
|
|
8d26842aab | ||
|
|
76e654304b | ||
|
|
d73b684999 | ||
|
|
a78bd8d7ca | ||
|
|
2ca53c1004 | ||
|
|
d621516d59 | ||
|
|
ef310cc3cc | ||
|
|
776c867c0b | ||
|
|
8abe0ec333 | ||
|
|
e57ced0ce7 | ||
|
|
117c46341b | ||
|
|
ba1ac69151 | ||
|
|
a8d3af35de | ||
|
|
307eed86e3 | ||
|
|
3f103323c7 | ||
|
|
05df3ca064 | ||
|
|
356884cf58 | ||
|
|
e68da7354e | ||
|
|
c59cd66141 | ||
|
|
9fa8fe5767 | ||
|
|
4ae0bc25c2 | ||
|
|
de81a8940e | ||
|
|
a73da0d81d | ||
|
|
32ba679719 | ||
|
|
cac0fefcdb | ||
|
|
498c76dd96 | ||
|
|
7526182304 | ||
|
|
d46bbd9cbf | ||
|
|
e98b537499 | ||
|
|
fc9d8509e5 | ||
|
|
7c6bbb61b5 | ||
|
|
8501ddc87f | ||
|
|
7d9b94525e | ||
|
|
eb02f0eadf | ||
|
|
69a8ba5aec | ||
|
|
fe49b8e618 | ||
|
|
26bf4dde5f | ||
|
|
e9b73050ba | ||
|
|
bacd0ab43f | ||
|
|
e438051371 | ||
|
|
314155593d | ||
|
|
787f819ce0 | ||
|
|
3632a62ea3 | ||
|
|
c7294df007 | ||
|
|
e3ad7fe3c0 | ||
|
|
6213683ddf | ||
|
|
a4ddfc9970 | ||
|
|
7ff271f9b9 | ||
|
|
d75cdd63a9 | ||
|
|
0a7575d1e4 | ||
|
|
ec3022d8ad | ||
|
|
0733562c0d | ||
|
|
d42103b91b | ||
|
|
00f7d08b04 | ||
|
|
408cc383cb | ||
|
|
5c926d0ac6 | ||
|
|
5cb88782fc | ||
|
|
5eef4e9ece | ||
|
|
04a2124141 | ||
|
|
1b6229b2a1 | ||
|
|
bca6db50a7 | ||
|
|
f3aae26996 | ||
|
|
f3c17a8e0f | ||
|
|
d6b24f8753 | ||
|
|
253db0a303 | ||
|
|
8499e52461 | ||
|
|
d0153179a9 | ||
|
|
264d03727e | ||
|
|
544405d9b9 | ||
|
|
24488a3b67 | ||
|
|
ae78185b29 | ||
|
|
7f682b24ef | ||
|
|
d42a52d8cf | ||
|
|
b85df15890 | ||
|
|
393499f34f | ||
|
|
c656d0f9b5 | ||
|
|
32017a8859 | ||
|
|
d87c5b1140 | ||
|
|
f59f783d3f | ||
|
|
ec298eac61 | ||
|
|
81a25bb4ee | ||
|
|
e99f044e45 | ||
|
|
5ae25a5fd9 | ||
|
|
e9d1cb4907 | ||
|
|
99f8ca2dca | ||
|
|
ddea5d38b5 | ||
|
|
31d2b83550 | ||
|
|
5535e56ed2 | ||
|
|
d740b95dbc | ||
|
|
ae92e9a945 | ||
|
|
29730c3896 | ||
|
|
a5ae8270f0 | ||
|
|
54f5fa6432 | ||
|
|
0260644063 | ||
|
|
267fc03a82 | ||
|
|
bf1537584c | ||
|
|
9ee7825022 | ||
|
|
2be0c42dd1 | ||
|
|
3423c053a2 | ||
|
|
26923cca00 | ||
|
|
36e027659c | ||
|
|
f447dccdb4 | ||
|
|
69eae32851 | ||
|
|
aa2fcfb8cb | ||
|
|
fae5ef2a41 | ||
|
|
7251ca7d2d | ||
|
|
7cdbd919bf | ||
|
|
d450f95602 | ||
|
|
5a65201971 | ||
|
|
d303b8db3e | ||
|
|
06baa33827 | ||
|
|
42743e637e | ||
|
|
9969fd7dec | ||
|
|
fc6d5c2a1d | ||
|
|
f8abb1ca24 | ||
|
|
a5af38ae3d | ||
|
|
aab70951dc | ||
|
|
334cacf93c | ||
|
|
53024012fc | ||
|
|
86a72f77c1 | ||
|
|
bc11a5ad0a | ||
|
|
8f2d217fd4 | ||
|
|
183727cd50 | ||
|
|
676e87591a | ||
|
|
8c05fc4da0 | ||
|
|
2bab06561e | ||
|
|
dfa7e2f5bb | ||
|
|
78bece5616 | ||
|
|
eeea15e373 | ||
|
|
80cd513ab7 | ||
|
|
942ef1615e | ||
|
|
a354698022 | ||
|
|
0cdea488c9 | ||
|
|
4f4291ac47 | ||
|
|
bf0cf03091 | ||
|
|
f7da09f20f | ||
|
|
be1529331c | ||
|
|
301d658a29 | ||
|
|
1cc54e5b2c | ||
|
|
65a7fd21e7 | ||
|
|
856537c0cd | ||
|
|
b2a88e0063 | ||
|
|
85a7068785 | ||
|
|
cbb733d99a | ||
|
|
ce88c94a19 | ||
|
|
16516915d8 | ||
|
|
6addb8da23 | ||
|
|
bc7f664fd8 | ||
|
|
aac17aa33c | ||
|
|
825500e207 | ||
|
|
4d42016c72 | ||
|
|
9d665df602 | ||
|
|
9087f69fb0 | ||
|
|
2a06f6a214 | ||
|
|
78a8428bd0 | ||
|
|
0d235768fa | ||
|
|
af092bbdec | ||
|
|
1cc07901f6 | ||
|
|
4961630d62 | ||
|
|
81920b9ab9 | ||
|
|
9e031d3b5b | ||
|
|
7ae3ed6d2a | ||
|
|
05d79f2b51 | ||
|
|
274e591354 | ||
|
|
95fd152b3d | ||
|
|
ffc91ed6d8 | ||
|
|
de0b759875 | ||
|
|
f041dcf944 | ||
|
|
946b9bd9d1 | ||
|
|
db77a69838 | ||
|
|
d10f4d26e2 | ||
|
|
6b62d686ba | ||
|
|
065826e64d | ||
|
|
a3b096343f | ||
|
|
b33be91b06 | ||
|
|
a94a1816c5 | ||
|
|
9a9e7fea07 | ||
|
|
9a03042077 | ||
|
|
704d3b2d6b | ||
|
|
e5c2be238d | ||
|
|
9feea07527 | ||
|
|
b0967d03b8 | ||
|
|
d33fd71f93 | ||
|
|
226b5b2682 | ||
|
|
f8879b0223 | ||
|
|
ada09d96c4 | ||
|
|
f0230d4634 | ||
|
|
228ad1044e | ||
|
|
a9ea0e223d | ||
|
|
37e8237f78 | ||
|
|
40deb19837 | ||
|
|
a9deb681e0 | ||
|
|
018e638ae3 | ||
|
|
967d271667 | ||
|
|
4e92a16d8d | ||
|
|
b4bcda12c2 | ||
|
|
e5bb902cd4 | ||
|
|
a3817fd5cd | ||
|
|
3a6338e9fb | ||
|
|
34d2342bdb | ||
|
|
5623a6b662 | ||
|
|
de0cc63d53 | ||
|
|
cb4892ace3 | ||
|
|
3cd17d7409 | ||
|
|
2848402e97 | ||
|
|
7e8f1acf67 | ||
|
|
8aa8a77260 | ||
|
|
ea4e078c92 | ||
|
|
21261f732f | ||
|
|
4e9d65089c | ||
|
|
e4f6dfbf78 | ||
|
|
9083784ffd | ||
|
|
6c4c4dbac9 | ||
|
|
ea0abf15ce | ||
|
|
71cccc5bdc | ||
|
|
4964928ac0 | ||
|
|
7fde60a267 | ||
|
|
306ed2ae0e | ||
|
|
a7cfe36b2e | ||
|
|
f4879a9e8a | ||
|
|
c8e09fcd90 | ||
|
|
c5f20d323c | ||
|
|
e3dcdf2f41 | ||
|
|
82d8b5d61e | ||
|
|
47692656e4 | ||
|
|
b5bf06b37a | ||
|
|
bc3b1e5f7c | ||
|
|
63eae15191 | ||
|
|
848b6dcef3 | ||
|
|
dfcdd71057 | ||
|
|
7368945bf3 | ||
|
|
de52203e89 | ||
|
|
62d1a3e01f | ||
|
|
68b4ecadf5 | ||
|
|
7831774703 | ||
|
|
52984d4b70 | ||
|
|
0b457f9a1e | ||
|
|
01cfd448f0 | ||
|
|
c189ebd8ca | ||
|
|
b35d11c9ed | ||
|
|
5fa5908072 | ||
|
|
a89f2754d3 | ||
|
|
453ae55db0 | ||
|
|
c1a5bdd7ae | ||
|
|
d19e702084 | ||
|
|
e02a22eaea | ||
|
|
63f3d63518 | ||
|
|
0d03ebfe96 | ||
|
|
074da855c1 | ||
|
|
9a028b9d5d | ||
|
|
a502980a39 | ||
|
|
1a1f6e5131 | ||
|
|
a67501e6de | ||
|
|
1f4164aca3 | ||
|
|
25e05f9855 | ||
|
|
1555799533 | ||
|
|
93d5211d27 | ||
|
|
de38fea917 | ||
|
|
3a3bc1c0db | ||
|
|
b5871d974e | ||
|
|
2985c3201b | ||
|
|
cf2fcd8221 | ||
|
|
2cb21a43c5 | ||
|
|
bae0a3f93b | ||
|
|
a853c45ec7 | ||
|
|
6cb6c88cd1 | ||
|
|
077f2b4435 | ||
|
|
8c3c4860f8 | ||
|
|
143592f724 | ||
|
|
dc404706c5 | ||
|
|
7a80e9e104 | ||
|
|
d7aae81c41 | ||
|
|
745c7e8470 | ||
|
|
52623350bd | ||
|
|
7d2c030ebd | ||
|
|
b841326e19 | ||
|
|
23c41f18de | ||
|
|
44e11e1a51 | ||
|
|
798d8e7a14 | ||
|
|
29748cf114 | ||
|
|
f5794b1355 |
@@ -1 +1 @@
|
||||
ko_fi: gpxstudio
|
||||
open_collective: gpxstudio
|
||||
|
||||
@@ -8,12 +8,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: |
|
||||
gpx/package-lock.json
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
- name: Create env file
|
||||
run: |
|
||||
touch website/.env
|
||||
echo PUBLIC_MAPBOX_TOKEN=${{ secrets.PUBLIC_MAPBOX_TOKEN }} >> website/.env
|
||||
echo PUBLIC_MAPTILER_KEY=${{ secrets.PUBLIC_MAPTILER_KEY }} >> website/.env
|
||||
cat website/.env
|
||||
|
||||
- name: Build website
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
npm run build --prefix website
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
uses: actions/upload-pages-artifact@v4
|
||||
with:
|
||||
path: 'website/build/'
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
website/src/lib/components/ui
|
||||
website/src/lib/docs/**/*.mdx
|
||||
**/*.webmanifest
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"useTabs": false,
|
||||
"tabWidth": 4,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 100,
|
||||
"overrides": [
|
||||
{
|
||||
"files": "**/*.svelte",
|
||||
"options": {
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"parser": "svelte"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode",
|
||||
"svelte.svelte-vscode"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[svelte]": {
|
||||
"editor.defaultFormatter": "svelte.svelte-vscode"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 gpx.studio
|
||||
Copyright (c) 2026 gpx.studio
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
[**gpx.studio**](https://gpx.studio) is an online tool for creating and editing GPX files.
|
||||
|
||||

|
||||

|
||||
|
||||
This repository contains the source code of the website.
|
||||
|
||||
@@ -26,6 +26,7 @@ Any help is greatly appreciated!
|
||||
## Development
|
||||
|
||||
The code is split into two parts:
|
||||
|
||||
- `gpx`: a Typescript library for parsing and manipulating GPX files,
|
||||
- `website`: the website itself, which is a [SvelteKit](https://kit.svelte.dev/) application.
|
||||
|
||||
@@ -41,11 +42,11 @@ npm run build
|
||||
|
||||
### Running the website
|
||||
|
||||
To be able to load the map, you will need to create your own <a href="https://account.mapbox.com/auth/signup" target="_blank">Mapbox access token</a> and store it in a `.env` file in the `website` directory.
|
||||
To be able to load the map, you will need to create your own <a href="https://cloud.maptiler.com/auth/widget?next=https://cloud.maptiler.com/maps/" target="_blank">MapTiler key</a> and store it in a `.env` file in the `website` directory.
|
||||
|
||||
```bash
|
||||
cd website
|
||||
echo PUBLIC_MAPBOX_TOKEN={YOUR_MAPBOX_TOKEN} >> .env
|
||||
echo PUBLIC_MAPTILER_KEY={YOUR_MAPTILER_KEY} >> .env
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
@@ -57,10 +58,9 @@ This project has been made possible thanks to the following open source projects
|
||||
- Development:
|
||||
- [Svelte](https://github.com/sveltejs/svelte) and [SvelteKit](https://github.com/sveltejs/kit) — seamless development experience
|
||||
- [MDsveX](https://github.com/pngwn/MDsveX) — allowing a Markdown-based documentation
|
||||
- [svelte-i18n](https://github.com/kaisermann/svelte-i18n) — easy localization
|
||||
- Design:
|
||||
- [shadcn-svelte](https://github.com/huntabyte/shadcn-svelte) — beautiful components
|
||||
- [lucide-svelte](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-svelte) — beautiful icons
|
||||
- [@lucide/svelte](https://github.com/lucide-icons/lucide/tree/main/packages/svelte) — beautiful icons
|
||||
- [tailwindcss](https://github.com/tailwindlabs/tailwindcss) — easy styling
|
||||
- [Chart.js](https://github.com/chartjs/Chart.js) — beautiful and fast charts
|
||||
- Logic:
|
||||
@@ -69,9 +69,10 @@ This project has been made possible thanks to the following open source projects
|
||||
- [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) — fast GPX file parsing
|
||||
- [SortableJS](https://github.com/SortableJS/Sortable) — creating a sortable file tree
|
||||
- Mapping:
|
||||
- [Mapbox GL JS](https://github.com/mapbox/mapbox-gl-js) — beautiful and fast interactive maps
|
||||
- [brouter](https://github.com/abrensch/brouter) — routing engine
|
||||
- [OpenStreetMap](https://www.openstreetmap.org) — map data used by Mapbox and brouter
|
||||
- [MapLibre GL JS](https://github.com/maplibre/maplibre-gl-js) — beautiful and fast interactive map rendering
|
||||
- [GraphHopper](https://github.com/graphhopper/graphhopper) — powerful routing engine
|
||||
- [OpenStreetMap](https://www.openstreetmap.org) — open map data used by most of the map layers, and by the routing engine
|
||||
- [Mapterhorn](https://github.com/mapterhorn/mapterhorn) — high-quality open terrain data used by some map layers (including for 3D), and by the routing engine
|
||||
- Search:
|
||||
- [DocSearch](https://github.com/algolia/docsearch) — search engine for the documentation
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
target/
|
||||
pkg/
|
||||
@@ -0,0 +1,367 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3eb0f42d6c360dc3f8a821f6bf2fdea7f72bfd36b3076eb0e6d1e9e0752fff4"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gpx-rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"quick-xml",
|
||||
"uuid",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.189"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41b1177fdf999d2321d3fb46ff47159d9c1fb9ad66a4879f8c50a0b504615e9b"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "gpx-rs"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.45"
|
||||
quick-xml = "0.42.0"
|
||||
uuid = {version = "1.26.1", features = ["v4", "js"]}
|
||||
wasm-bindgen = "0.2"
|
||||
@@ -0,0 +1,274 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1"
|
||||
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd
|
||||
http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd
|
||||
http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd
|
||||
http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1"
|
||||
creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>simple</name>
|
||||
<desc>description</desc>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio">
|
||||
<text>link text</text>
|
||||
</link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>track name</name>
|
||||
<cmt>track comment</cmt>
|
||||
<desc>track description</desc>
|
||||
<src>track source</src>
|
||||
<link href="https://gpx.studio">
|
||||
<text>track link text</text>
|
||||
</link>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78279" lon="4.406021">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782714" lon="4.406018">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782607" lon="4.406047">
|
||||
<ele>113.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782405" lon="4.406194">
|
||||
<ele>114.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,660 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_cad</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>with_cad</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78279" lon="4.406021">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782714" lon="4.406018">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782607" lon="4.406047">
|
||||
<ele>113.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782405" lon="4.406194">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>80</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:cad>90</gpxtpx:cad>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,660 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_hr</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>with_hr</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78279" lon="4.406021">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782714" lon="4.406018">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782607" lon="4.406047">
|
||||
<ele>113.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782405" lon="4.406194">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>150</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:hr>160</gpxtpx:hr>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,500 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_power</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>with_power</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78279" lon="4.406021">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782714" lon="4.406018">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782607" lon="4.406047">
|
||||
<ele>113.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782405" lon="4.406194">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<power>200</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
<extensions>
|
||||
<power>210</power>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,665 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1"
|
||||
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd
|
||||
http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd
|
||||
http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd
|
||||
http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxpx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1"
|
||||
creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_power</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>with_power</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78279" lon="4.406021">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782714" lon="4.406018">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782607" lon="4.406047">
|
||||
<ele>113.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782405" lon="4.406194">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>200</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
<extensions>
|
||||
<gpxpx:PowerExtension>
|
||||
<gpxpx:PowerInWatts>210</gpxpx:PowerInWatts>
|
||||
</gpxpx:PowerExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,253 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_routes</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<rte>
|
||||
<name>route 1</name>
|
||||
<type>Cycling</type>
|
||||
<rtept lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
</rtept>
|
||||
</rte>
|
||||
<rte>
|
||||
<name>route 2</name>
|
||||
<type>Cycling</type>
|
||||
<rtept lat="50.782212" lon="4.406377">
|
||||
<ele>115.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
</rtept>
|
||||
<rtept lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
</rtept>
|
||||
</rte>
|
||||
</gpx>
|
||||
@@ -0,0 +1,253 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_segments</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>with_segments</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
<trkseg>
|
||||
<trkpt lat="50.782212" lon="4.406377">
|
||||
<ele>115.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,267 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_style</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>with_style</name>
|
||||
<type>Cycling</type>
|
||||
<extensions>
|
||||
<gpx_style:line>
|
||||
<gpx_style:color>2d3ee9</gpx_style:color>
|
||||
<gpx_style:opacity>0.5</gpx_style:opacity>
|
||||
<gpx_style:width>6</gpx_style:width>
|
||||
</gpx_style:line>
|
||||
</extensions>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78279" lon="4.406021">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782714" lon="4.406018">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782607" lon="4.406047">
|
||||
<ele>113.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782405" lon="4.406194">
|
||||
<ele>114.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,820 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_surface</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>with_surface</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78279" lon="4.406021">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782714" lon="4.406018">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782607" lon="4.406047">
|
||||
<ele>113.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782405" lon="4.406194">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>asphalt</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:Extensions>
|
||||
<surface>cobblestone</surface>
|
||||
</gpxtpx:Extensions>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,660 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_temp</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>with_temp</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78279" lon="4.406021">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782714" lon="4.406018">
|
||||
<ele>113.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782607" lon="4.406047">
|
||||
<ele>113.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782405" lon="4.406194">
|
||||
<ele>114.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>21</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:atemp>22</gpxtpx:atemp>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,340 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_time</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>with_time</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
<time>2023-12-31T23:00:00.000Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
<time>2023-12-31T23:00:03.180Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
<time>2023-12-31T23:00:11.254Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
<time>2023-12-31T23:00:14.795Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
<time>2023-12-31T23:00:17.957Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
<time>2023-12-31T23:00:21.759Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
<time>2023-12-31T23:00:29.948Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
<time>2023-12-31T23:00:36.098Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
<time>2023-12-31T23:00:42.396Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
<time>2023-12-31T23:00:45.636Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
<time>2023-12-31T23:00:48.827Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
<time>2023-12-31T23:00:55.249Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
<time>2023-12-31T23:01:00.794Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
<time>2023-12-31T23:01:03.708Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
<time>2023-12-31T23:01:06.542Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
<time>2023-12-31T23:01:11.014Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
<time>2023-12-31T23:01:14.108Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
<time>2023-12-31T23:01:17.026Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
<time>2023-12-31T23:01:19.742Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
<time>2023-12-31T23:01:28.110Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
<time>2023-12-31T23:01:31.328Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
<time>2023-12-31T23:01:35.306Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
<time>2023-12-31T23:01:36.830Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
<time>2023-12-31T23:01:38.701Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
<time>2023-12-31T23:01:40.022Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
<time>2023-12-31T23:01:41.920Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
<time>2023-12-31T23:01:48.333Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
<time>2023-12-31T23:01:52.195Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
<time>2023-12-31T23:01:55.766Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
<time>2023-12-31T23:01:58.740Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
<time>2023-12-31T23:02:04.091Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
<time>2023-12-31T23:02:12.713Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
<time>2023-12-31T23:02:14.875Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
<time>2023-12-31T23:02:16.638Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
<time>2023-12-31T23:02:18.384Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
<time>2023-12-31T23:02:25.735Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
<time>2023-12-31T23:02:27.404Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
<time>2023-12-31T23:02:29.642Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
<time>2023-12-31T23:02:31.271Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
<time>2023-12-31T23:02:32.974Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
<time>2023-12-31T23:02:34.725Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
<time>2023-12-31T23:02:36.057Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
<time>2023-12-31T23:02:37.639Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
<time>2023-12-31T23:02:39.280Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
<time>2023-12-31T23:02:41.205Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
<time>2023-12-31T23:02:43.731Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
<time>2023-12-31T23:02:54.830Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
<time>2023-12-31T23:02:59.232Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
<time>2023-12-31T23:03:01.951Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78279" lon="4.406021">
|
||||
<ele>113.5</ele>
|
||||
<time>2023-12-31T23:03:03.598Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782714" lon="4.406018">
|
||||
<ele>113.5</ele>
|
||||
<time>2023-12-31T23:03:05.119Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782607" lon="4.406047">
|
||||
<ele>113.8</ele>
|
||||
<time>2023-12-31T23:03:07.291Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782405" lon="4.406194">
|
||||
<ele>114.8</ele>
|
||||
<time>2023-12-31T23:03:11.741Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
<time>2023-12-31T23:03:17.114Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
<time>2023-12-31T23:03:28.573Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
<time>2023-12-31T23:03:32.796Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
<time>2023-12-31T23:03:38.750Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
<time>2023-12-31T23:03:41.922Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
<time>2023-12-31T23:03:45.133Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
<time>2023-12-31T23:03:48.867Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
<time>2023-12-31T23:03:56.536Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
<time>2023-12-31T23:04:00.561Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
<time>2023-12-31T23:04:03.346Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
<time>2023-12-31T23:04:06.761Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
<time>2023-12-31T23:04:14.339Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
<time>2023-12-31T23:04:23.699Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
<time>2023-12-31T23:04:27.973Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
<time>2023-12-31T23:04:32.307Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
<time>2023-12-31T23:04:44.408Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
<time>2023-12-31T23:04:48.146Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
<time>2023-12-31T23:05:00.532Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
<time>2023-12-31T23:05:11.852Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
<time>2023-12-31T23:05:23.300Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
<time>2023-12-31T23:05:41.944Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
<time>2023-12-31T23:05:49.538Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
<time>2023-12-31T23:05:57.109Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
<time>2023-12-31T23:06:03.116Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
<time>2023-12-31T23:06:14.336Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
<time>2023-12-31T23:06:26.353Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
<time>2023-12-31T23:06:40.567Z</time>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,257 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_tracks</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>track 1</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
<trk>
|
||||
<name>track 2</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.782212" lon="4.406377">
|
||||
<ele>115.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,346 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1" creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_tracks_and_segments</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>track 1</name>
|
||||
<type>Running</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
<time>2023-12-31T23:00:00.000Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
<time>2023-12-31T23:00:03.180Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
<time>2023-12-31T23:00:11.254Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
<time>2023-12-31T23:00:14.795Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
<time>2023-12-31T23:00:17.957Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
<time>2023-12-31T23:00:21.759Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
<time>2023-12-31T23:00:29.948Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
<time>2023-12-31T23:00:36.098Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
<time>2023-12-31T23:00:42.396Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
<time>2023-12-31T23:00:45.636Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
<time>2023-12-31T23:00:48.827Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
<time>2023-12-31T23:00:55.249Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
<time>2023-12-31T23:01:00.794Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
<time>2023-12-31T23:01:03.708Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
<time>2023-12-31T23:01:06.542Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
<time>2023-12-31T23:01:11.014Z</time>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
<trkseg>
|
||||
<trkpt lat="50.78727108169855" lon="4.406133681127736">
|
||||
<ele>115.0</ele>
|
||||
<time>2023-12-31T23:01:14.708Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
<time>2023-12-31T23:01:15.462Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
<time>2023-12-31T23:01:18.380Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
<time>2023-12-31T23:01:21.096Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
<time>2023-12-31T23:01:29.464Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
<time>2023-12-31T23:01:32.682Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
<time>2023-12-31T23:01:36.660Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
<time>2023-12-31T23:01:38.184Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
<time>2023-12-31T23:01:40.055Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
<time>2023-12-31T23:01:41.376Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
<time>2023-12-31T23:01:43.274Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
<time>2023-12-31T23:01:49.687Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
<time>2023-12-31T23:01:53.549Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
<time>2023-12-31T23:01:57.120Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
<time>2023-12-31T23:02:00.094Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
<time>2023-12-31T23:02:05.445Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
<time>2023-12-31T23:02:14.067Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
<time>2023-12-31T23:02:16.229Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
<time>2023-12-31T23:02:17.992Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
<time>2023-12-31T23:02:19.738Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
<time>2023-12-31T23:02:27.089Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
<time>2023-12-31T23:02:28.758Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
<time>2023-12-31T23:02:30.996Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
<time>2023-12-31T23:02:32.625Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
<time>2023-12-31T23:02:34.328Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
<time>2023-12-31T23:02:36.079Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
<time>2023-12-31T23:02:37.411Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
<time>2023-12-31T23:02:38.993Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
<time>2023-12-31T23:02:40.634Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
<time>2023-12-31T23:02:42.559Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
<time>2023-12-31T23:02:45.085Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
<time>2023-12-31T23:02:56.184Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
<time>2023-12-31T23:03:00.586Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
<time>2023-12-31T23:03:03.305Z</time>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
<trk>
|
||||
<name>track 2</name>
|
||||
<type>Running</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.782212" lon="4.406377">
|
||||
<ele>115.5</ele>
|
||||
<time>2023-12-31T23:03:17.151Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
<time>2023-12-31T23:03:18.020Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
<time>2023-12-31T23:03:29.479Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
<time>2023-12-31T23:03:33.702Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
<time>2023-12-31T23:03:39.656Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
<time>2023-12-31T23:03:42.828Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
<time>2023-12-31T23:03:46.039Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
<time>2023-12-31T23:03:49.773Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
<time>2023-12-31T23:03:57.442Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
<time>2023-12-31T23:04:01.467Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
<time>2023-12-31T23:04:04.252Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
<time>2023-12-31T23:04:07.667Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
<time>2023-12-31T23:04:15.245Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
<time>2023-12-31T23:04:24.605Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
<time>2023-12-31T23:04:28.879Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
<time>2023-12-31T23:04:33.213Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
<time>2023-12-31T23:04:45.314Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
<time>2023-12-31T23:04:49.052Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
<time>2023-12-31T23:05:01.438Z</time>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
<trkseg>
|
||||
<trkpt lat="50.77906316558724" lon="4.412547477922485">
|
||||
<ele>133.3</ele>
|
||||
<time>2023-12-31T23:05:03.324Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
<time>2023-12-31T23:05:12.804Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
<time>2023-12-31T23:05:24.252Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
<time>2023-12-31T23:05:42.896Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
<time>2023-12-31T23:05:50.490Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
<time>2023-12-31T23:05:58.061Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
<time>2023-12-31T23:06:04.068Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
<time>2023-12-31T23:06:15.288Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
<time>2023-12-31T23:06:27.305Z</time>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
<time>2023-12-31T23:06:41.519Z</time>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,276 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1"
|
||||
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd
|
||||
http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd
|
||||
http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd
|
||||
http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
|
||||
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
|
||||
xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2" version="1.1"
|
||||
creator="https://gpx.studio">
|
||||
<metadata>
|
||||
<name>with_waypoint</name>
|
||||
<author>
|
||||
<name>gpx.studio</name>
|
||||
<link href="https://gpx.studio"></link>
|
||||
</author>
|
||||
</metadata>
|
||||
<wpt lat="50.7836710064975" lon="4.410764082658738">
|
||||
<ele>122.0</ele>
|
||||
<name>waypoint name</name>
|
||||
<cmt>waypoint comment</cmt>
|
||||
<desc>waypoint description</desc>
|
||||
<link href="https://gpx.studio">
|
||||
<text>waypoint link text</text>
|
||||
</link>
|
||||
<sym>Bike Trail</sym>
|
||||
<type>Bike Trail</type>
|
||||
</wpt>
|
||||
<trk>
|
||||
<name>with_waypoint</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="50.790867" lon="4.404968">
|
||||
<ele>109.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790714" lon="4.405036">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790336" lon="4.405259">
|
||||
<ele>110.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790165" lon="4.405331">
|
||||
<ele>110.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.790008" lon="4.405359">
|
||||
<ele>110.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789818" lon="4.405359">
|
||||
<ele>109.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789409" lon="4.40534">
|
||||
<ele>107.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.789105" lon="4.405411">
|
||||
<ele>106.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788799" lon="4.405527">
|
||||
<ele>108.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.788645" lon="4.405606">
|
||||
<ele>109.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.7885" lon="4.405711">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78822" lon="4.405959">
|
||||
<ele>112.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787956" lon="4.406092">
|
||||
<ele>112.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787814" lon="4.406143">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787674" lon="4.406177">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787451" lon="4.406199">
|
||||
<ele>115.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787297" lon="4.406177">
|
||||
<ele>114.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78716" lon="4.406098">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.787045" lon="4.405984">
|
||||
<ele>114.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786683" lon="4.405653">
|
||||
<ele>114.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786538" lon="4.405543">
|
||||
<ele>115.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78635" lon="4.405441">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786275" lon="4.40542">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786182" lon="4.405435">
|
||||
<ele>116.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786121" lon="4.405475">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.786042" lon="4.405558">
|
||||
<ele>115.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785821" lon="4.405925">
|
||||
<ele>114.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785672" lon="4.406119">
|
||||
<ele>112.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785516" lon="4.406256">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785384" lon="4.406364">
|
||||
<ele>109.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.785126" lon="4.406475">
|
||||
<ele>106.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784697" lon="4.406537">
|
||||
<ele>104.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784591" lon="4.40657">
|
||||
<ele>104.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784507" lon="4.406612">
|
||||
<ele>103.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784435" lon="4.40669">
|
||||
<ele>103.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784209" lon="4.407148">
|
||||
<ele>103.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784162" lon="4.407257">
|
||||
<ele>103.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784077" lon="4.407372">
|
||||
<ele>104.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.784006" lon="4.407435">
|
||||
<ele>105.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783924" lon="4.407471">
|
||||
<ele>106.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783837" lon="4.407486">
|
||||
<ele>107.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783771" lon="4.407472">
|
||||
<ele>108.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783697" lon="4.407428">
|
||||
<ele>109.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783626" lon="4.407363">
|
||||
<ele>110.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783548" lon="4.407274">
|
||||
<ele>110.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783458" lon="4.407134">
|
||||
<ele>110.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.783123" lon="4.406435">
|
||||
<ele>111.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782982" lon="4.406168">
|
||||
<ele>112.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782871" lon="4.406044">
|
||||
<ele>113.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78279" lon="4.406021">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782714" lon="4.406018">
|
||||
<ele>113.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782607" lon="4.406047">
|
||||
<ele>113.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782405" lon="4.406194">
|
||||
<ele>114.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.782175" lon="4.406413">
|
||||
<ele>115.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781749" lon="4.407018">
|
||||
<ele>118.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781654" lon="4.407316">
|
||||
<ele>119.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781563" lon="4.407764">
|
||||
<ele>121.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781487" lon="4.407984">
|
||||
<ele>122.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781422" lon="4.408216">
|
||||
<ele>122.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781395" lon="4.408508">
|
||||
<ele>123.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781399" lon="4.409114">
|
||||
<ele>126.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781367" lon="4.409428">
|
||||
<ele>128.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.781286" lon="4.409607">
|
||||
<ele>129.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.78116" lon="4.409789">
|
||||
<ele>130.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780804" lon="4.409993">
|
||||
<ele>130.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780389" lon="4.410334">
|
||||
<ele>131.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780232" lon="4.410563">
|
||||
<ele>132.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.780094" lon="4.410827">
|
||||
<ele>132.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779723" lon="4.411582">
|
||||
<ele>135.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779591" lon="4.411791">
|
||||
<ele>135.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.779125" lon="4.412435">
|
||||
<ele>132.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778676" lon="4.412979">
|
||||
<ele>134.0</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.778194" lon="4.413466">
|
||||
<ele>136.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777427" lon="4.414302">
|
||||
<ele>137.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.777165" lon="4.414736">
|
||||
<ele>137.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776927" lon="4.415201">
|
||||
<ele>137.5</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776778" lon="4.415613">
|
||||
<ele>137.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776553" lon="4.416425">
|
||||
<ele>134.8</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776326" lon="4.417304">
|
||||
<ele>132.3</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="50.776129" lon="4.418383">
|
||||
<ele>129.5</ele>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
@@ -0,0 +1,3 @@
|
||||
mod parse;
|
||||
|
||||
pub use parse::*;
|
||||
@@ -0,0 +1,637 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::gpx::{
|
||||
Author, GPXFile, Link, LngLat, Track, TrackSegment, Trackpoint, TrackpointChunk, Waypoint,
|
||||
WaypointChunk,
|
||||
};
|
||||
use chrono::DateTime;
|
||||
use quick_xml::Error;
|
||||
use quick_xml::events::Event;
|
||||
use quick_xml::events::attributes::Attributes;
|
||||
use quick_xml::reader::Reader;
|
||||
|
||||
enum GPXElement {
|
||||
METADATA,
|
||||
NAME,
|
||||
COMMENT,
|
||||
DESCRIPTION,
|
||||
SOURCE,
|
||||
AUTHOR(Author),
|
||||
LINK(Link),
|
||||
TEXT,
|
||||
TRACK(Track),
|
||||
SEGMENT(TrackSegment),
|
||||
TRACKPOINT(Trackpoint),
|
||||
WAYPOINT(Waypoint),
|
||||
ELEVATION,
|
||||
TIME,
|
||||
TEMPERATURE,
|
||||
HEARTRATE,
|
||||
CADENCE,
|
||||
POWER,
|
||||
SYMBOL,
|
||||
TYPE,
|
||||
COLOR,
|
||||
OPACITY,
|
||||
WIDTH,
|
||||
}
|
||||
|
||||
fn parse_coordinates(attributes: Attributes<'_>) -> LngLat {
|
||||
let mut coordinates = LngLat::default();
|
||||
for attr in attributes {
|
||||
if let Ok(attr) = attr {
|
||||
match attr.key.as_ref() {
|
||||
"lat" => coordinates.lat = attr.value.parse().unwrap_or_default(),
|
||||
"lon" => coordinates.lng = attr.value.parse().unwrap_or_default(),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
coordinates
|
||||
}
|
||||
|
||||
pub fn parse(data: &[u8]) -> Result<GPXFile, Error> {
|
||||
let mut reader = Reader::from_reader(data);
|
||||
let mut buf = vec![];
|
||||
let mut gpx = GPXFile::default();
|
||||
let mut stack: Vec<GPXElement> = vec![];
|
||||
let mut trkpt_chunk = TrackpointChunk::default();
|
||||
let mut wpt_chunk = WaypointChunk::default();
|
||||
loop {
|
||||
match reader.read_event_into(&mut buf) {
|
||||
Ok(Event::Start(e)) => match e.name().as_ref() {
|
||||
"metadata" => stack.push(GPXElement::METADATA),
|
||||
"name" => stack.push(GPXElement::NAME),
|
||||
"cmt" => stack.push(GPXElement::COMMENT),
|
||||
"desc" => stack.push(GPXElement::DESCRIPTION),
|
||||
"src" => stack.push(GPXElement::SOURCE),
|
||||
"author" => stack.push(GPXElement::AUTHOR(Author::default())),
|
||||
"link" => {
|
||||
let mut link = Link::default();
|
||||
for attr in e.attributes() {
|
||||
if let Ok(attr) = attr {
|
||||
if attr.key.as_ref() == "href" {
|
||||
link.href = attr.value.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
stack.push(GPXElement::LINK(link));
|
||||
}
|
||||
"text" => stack.push(GPXElement::TEXT),
|
||||
"trk" => stack.push(GPXElement::TRACK(Track::default())),
|
||||
"trkseg" => {
|
||||
stack.push(GPXElement::SEGMENT(TrackSegment::default()));
|
||||
}
|
||||
"trkpt" => {
|
||||
let mut trkpt = Trackpoint::default();
|
||||
trkpt.coordinates = parse_coordinates(e.attributes());
|
||||
stack.push(GPXElement::TRACKPOINT(trkpt));
|
||||
}
|
||||
"wpt" => {
|
||||
let mut wpt = Waypoint::default();
|
||||
wpt.coordinates = parse_coordinates(e.attributes());
|
||||
stack.push(GPXElement::WAYPOINT(wpt));
|
||||
}
|
||||
"ele" => stack.push(GPXElement::ELEVATION),
|
||||
"time" => stack.push(GPXElement::TIME),
|
||||
e if e.ends_with("atemp") => stack.push(GPXElement::TEMPERATURE),
|
||||
e if e.ends_with("hr") => stack.push(GPXElement::HEARTRATE),
|
||||
e if e.ends_with("cad") => stack.push(GPXElement::CADENCE),
|
||||
"power" => stack.push(GPXElement::POWER),
|
||||
e if e.ends_with("PowerInWatts") => stack.push(GPXElement::POWER),
|
||||
"sym" => stack.push(GPXElement::SYMBOL),
|
||||
"type" => stack.push(GPXElement::TYPE),
|
||||
e if e.ends_with("color") => stack.push(GPXElement::COLOR),
|
||||
e if e.ends_with("opacity") => stack.push(GPXElement::OPACITY),
|
||||
e if e.ends_with("width") => stack.push(GPXElement::WIDTH),
|
||||
_ => (),
|
||||
},
|
||||
Ok(Event::End(e)) => match e.name().as_ref() {
|
||||
"gpx" => {
|
||||
if !wpt_chunk.wpt.is_empty() {
|
||||
gpx.wpt.push(Rc::new(wpt_chunk));
|
||||
wpt_chunk = WaypointChunk::default();
|
||||
}
|
||||
}
|
||||
"metadata" => {
|
||||
stack.pop();
|
||||
}
|
||||
"author" => {
|
||||
if let Some(GPXElement::AUTHOR(author)) = stack.pop() {
|
||||
gpx.info.author = Some(author);
|
||||
}
|
||||
}
|
||||
"link" => {
|
||||
if let Some(GPXElement::LINK(link)) = stack.pop() {
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::AUTHOR(author)) => {
|
||||
author.link = Some(link);
|
||||
}
|
||||
Some(GPXElement::TRACK(trk)) => {
|
||||
trk.info.link = Some(link);
|
||||
}
|
||||
Some(GPXElement::WAYPOINT(wpt)) => {
|
||||
wpt.link = Some(link);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
"trk" => {
|
||||
if let Some(GPXElement::TRACK(trk)) = stack.pop() {
|
||||
gpx.trk.push(trk);
|
||||
}
|
||||
}
|
||||
"trkseg" => {
|
||||
if let Some(GPXElement::SEGMENT(mut trkseg)) = stack.pop() {
|
||||
if let Some(GPXElement::TRACK(trk)) = stack.last_mut() {
|
||||
if !trkpt_chunk.trkpt.is_empty() {
|
||||
trkseg.push(trkpt_chunk);
|
||||
trkpt_chunk = TrackpointChunk::default();
|
||||
}
|
||||
trk.trkseg.push(trkseg);
|
||||
}
|
||||
}
|
||||
}
|
||||
"trkpt" => {
|
||||
if let Some(GPXElement::TRACKPOINT(trkpt)) = stack.pop() {
|
||||
if let Some(GPXElement::SEGMENT(trkseg)) = stack.last_mut() {
|
||||
trkpt_chunk.trkpt.push(trkpt);
|
||||
if trkpt_chunk.is_full() {
|
||||
trkseg.push(trkpt_chunk);
|
||||
trkpt_chunk = TrackpointChunk::default();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"wpt" => {
|
||||
if let Some(GPXElement::WAYPOINT(wpt)) = stack.pop() {
|
||||
wpt_chunk.wpt.push(wpt);
|
||||
if wpt_chunk.is_full() {
|
||||
gpx.wpt.push(Rc::new(wpt_chunk));
|
||||
wpt_chunk = WaypointChunk::default();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
Ok(Event::Text(e)) => match stack.last_mut() {
|
||||
Some(GPXElement::NAME) => {
|
||||
stack.pop();
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::METADATA) => {
|
||||
gpx.info.name = e.to_string();
|
||||
}
|
||||
Some(GPXElement::AUTHOR(author)) => {
|
||||
author.name = Some(e.to_string());
|
||||
}
|
||||
Some(GPXElement::TRACK(trk)) => {
|
||||
trk.info.name = Some(e.to_string());
|
||||
}
|
||||
Some(GPXElement::WAYPOINT(wpt)) => {
|
||||
wpt.name = Some(e.to_string());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Some(GPXElement::COMMENT) => {
|
||||
stack.pop();
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::TRACK(trk)) => {
|
||||
trk.info.cmt = Some(e.to_string());
|
||||
}
|
||||
Some(GPXElement::WAYPOINT(wpt)) => {
|
||||
wpt.cmt = Some(e.to_string());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Some(GPXElement::DESCRIPTION) => {
|
||||
stack.pop();
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::METADATA) => {
|
||||
gpx.info.desc = Some(e.to_string());
|
||||
}
|
||||
Some(GPXElement::TRACK(trk)) => {
|
||||
trk.info.desc = Some(e.to_string());
|
||||
}
|
||||
Some(GPXElement::WAYPOINT(wpt)) => {
|
||||
wpt.desc = Some(e.to_string());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Some(GPXElement::SOURCE) => {
|
||||
stack.pop();
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::TRACK(trk)) => {
|
||||
trk.info.src = Some(e.to_string());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Some(GPXElement::TEXT) => {
|
||||
stack.pop();
|
||||
if let Some(GPXElement::LINK(link)) = stack.last_mut() {
|
||||
link.text = Some(e.to_string());
|
||||
}
|
||||
}
|
||||
Some(GPXElement::ELEVATION) => {
|
||||
stack.pop();
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::TRACKPOINT(trkpt)) => {
|
||||
trkpt.ele = e.parse().unwrap_or_default();
|
||||
}
|
||||
Some(GPXElement::WAYPOINT(wpt)) => {
|
||||
wpt.ele = e.parse().unwrap_or_default();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Some(GPXElement::TIME) => {
|
||||
stack.pop();
|
||||
if let Some(GPXElement::TRACKPOINT(trkpt)) = stack.last_mut() {
|
||||
if let Ok(time) = DateTime::parse_from_rfc3339(e.as_ref()) {
|
||||
trkpt.time = Some(time.timestamp_millis());
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(GPXElement::TEMPERATURE) => {
|
||||
stack.pop();
|
||||
if let Some(GPXElement::TRACKPOINT(trkpt)) = stack.last_mut() {
|
||||
trkpt.atemp = e.parse().ok();
|
||||
}
|
||||
}
|
||||
Some(GPXElement::HEARTRATE) => {
|
||||
stack.pop();
|
||||
if let Some(GPXElement::TRACKPOINT(trkpt)) = stack.last_mut() {
|
||||
trkpt.hr = e.parse().ok();
|
||||
}
|
||||
}
|
||||
Some(GPXElement::CADENCE) => {
|
||||
stack.pop();
|
||||
if let Some(GPXElement::TRACKPOINT(trkpt)) = stack.last_mut() {
|
||||
trkpt.cad = e.parse().ok();
|
||||
}
|
||||
}
|
||||
Some(GPXElement::POWER) => {
|
||||
stack.pop();
|
||||
if let Some(GPXElement::TRACKPOINT(trkpt)) = stack.last_mut() {
|
||||
trkpt.power = e.parse().ok();
|
||||
}
|
||||
}
|
||||
Some(GPXElement::SYMBOL) => {
|
||||
stack.pop();
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::WAYPOINT(wpt)) => {
|
||||
wpt.sym = Some(e.to_string());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Some(GPXElement::TYPE) => {
|
||||
stack.pop();
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::TRACK(trk)) => {
|
||||
trk.info.type_ = Some(e.to_string());
|
||||
}
|
||||
Some(GPXElement::WAYPOINT(wpt)) => {
|
||||
wpt.type_ = Some(e.to_string());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Some(GPXElement::COLOR) => {
|
||||
stack.pop();
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::TRACK(trk)) => {
|
||||
let mut color = "#".to_string();
|
||||
color.push_str(&e);
|
||||
trk.info.color = Some(color);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Some(GPXElement::OPACITY) => {
|
||||
stack.pop();
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::TRACK(trk)) => {
|
||||
trk.info.opacity = e.parse().ok();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Some(GPXElement::WIDTH) => {
|
||||
stack.pop();
|
||||
match stack.last_mut() {
|
||||
Some(GPXElement::TRACK(trk)) => {
|
||||
trk.info.width = e.parse().ok();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
Ok(Event::Eof) => break,
|
||||
Err(e) => return Err(e),
|
||||
_ => (),
|
||||
}
|
||||
buf.clear();
|
||||
}
|
||||
Ok(gpx)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{fs::File, io::Read};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse_simple() {
|
||||
let mut f = File::open("data/simple.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.info.name, "simple");
|
||||
assert!(gpx.info.desc.is_some_and(|d| d == "description"));
|
||||
assert!(gpx.info.author.is_some());
|
||||
let author = gpx.info.author.as_ref().unwrap();
|
||||
assert!(author.name.as_ref().is_some_and(|n| n == "gpx.studio"));
|
||||
assert!(author.link.is_some());
|
||||
let link = author.link.as_ref().unwrap();
|
||||
assert_eq!(link.href, "https://gpx.studio");
|
||||
assert!(link.text.as_ref().is_some_and(|t| t == "link text"));
|
||||
|
||||
assert_eq!(gpx.trk.len(), 1);
|
||||
let trk = &gpx.trk[0];
|
||||
assert!(trk.info.name.as_ref().is_some_and(|n| n == "track name"));
|
||||
assert!(trk.info.cmt.as_ref().is_some_and(|c| c == "track comment"));
|
||||
assert!(
|
||||
trk.info
|
||||
.desc
|
||||
.as_ref()
|
||||
.is_some_and(|d| d == "track description")
|
||||
);
|
||||
assert!(trk.info.src.as_ref().is_some_and(|s| s == "track source"));
|
||||
assert!(trk.info.link.is_some());
|
||||
let link = trk.info.link.as_ref().unwrap();
|
||||
assert_eq!(link.href, "https://gpx.studio");
|
||||
assert!(link.text.as_ref().is_some_and(|t| t == "track link text"));
|
||||
assert!(trk.info.type_.as_ref().is_some_and(|c| c == "Cycling"));
|
||||
|
||||
assert_eq!(trk.trkseg.len(), 1);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert_eq!(trkseg.len(), 80);
|
||||
let trkpt = &trkseg[0];
|
||||
assert_eq!(trkpt.coordinates.lat, 50.790867);
|
||||
assert_eq!(trkpt.coordinates.lng, 4.404968);
|
||||
assert_eq!(trkpt.ele, 109.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_tracks() {
|
||||
let mut f = File::open("data/with_tracks.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.trk.len(), 2);
|
||||
let trk = &gpx.trk[0];
|
||||
assert!(trk.info.name.as_ref().is_some_and(|n| n == "track 1"));
|
||||
assert!(trk.info.type_.as_ref().is_some_and(|c| c == "Cycling"));
|
||||
|
||||
assert_eq!(trk.trkseg.len(), 1);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert_eq!(trkseg.len(), 49);
|
||||
let trkpt = &trkseg[0];
|
||||
assert_eq!(trkpt.coordinates.lat, 50.790867);
|
||||
assert_eq!(trkpt.coordinates.lng, 4.404968);
|
||||
assert_eq!(trkpt.ele, 109.0);
|
||||
|
||||
let trk = &gpx.trk[1];
|
||||
assert!(trk.info.name.as_ref().is_some_and(|n| n == "track 2"));
|
||||
assert!(trk.info.type_.as_ref().is_some_and(|c| c == "Cycling"));
|
||||
|
||||
assert_eq!(trk.trkseg.len(), 1);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert_eq!(trkseg.len(), 28);
|
||||
let trkpt = &trkseg[0];
|
||||
assert_eq!(trkpt.coordinates.lat, 50.782212);
|
||||
assert_eq!(trkpt.coordinates.lng, 4.406377);
|
||||
assert_eq!(trkpt.ele, 115.5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_segments() {
|
||||
let mut f = File::open("data/with_segments.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.trk.len(), 1);
|
||||
let trk = &gpx.trk[0];
|
||||
|
||||
assert_eq!(trk.trkseg.len(), 2);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert_eq!(trkseg.len(), 49);
|
||||
let trkpt = &trkseg[0];
|
||||
assert_eq!(trkpt.coordinates.lat, 50.790867);
|
||||
assert_eq!(trkpt.coordinates.lng, 4.404968);
|
||||
assert_eq!(trkpt.ele, 109.0);
|
||||
|
||||
let trkseg = &trk.trkseg[1];
|
||||
assert_eq!(trkseg.len(), 28);
|
||||
let trkpt = &trkseg[0];
|
||||
assert_eq!(trkpt.coordinates.lat, 50.782212);
|
||||
assert_eq!(trkpt.coordinates.lng, 4.406377);
|
||||
assert_eq!(trkpt.ele, 115.5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_tracks_and_segments() {
|
||||
let mut f = File::open("data/with_tracks_and_segments.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.trk.len(), 2);
|
||||
let trk = &gpx.trk[0];
|
||||
|
||||
assert_eq!(trk.trkseg.len(), 2);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert_eq!(trkseg.len(), 16);
|
||||
let trkpt = &trkseg[0];
|
||||
assert_eq!(trkpt.coordinates.lat, 50.790867);
|
||||
assert_eq!(trkpt.coordinates.lng, 4.404968);
|
||||
assert_eq!(trkpt.ele, 109.0);
|
||||
|
||||
let trkseg = &trk.trkseg[1];
|
||||
assert_eq!(trkseg.len(), 34);
|
||||
let trkpt = &trkseg[0];
|
||||
assert_eq!(trkpt.coordinates.lat, 50.78727108169855);
|
||||
assert_eq!(trkpt.coordinates.lng, 4.406133681127736);
|
||||
assert_eq!(trkpt.ele, 115.0);
|
||||
|
||||
let trk = &gpx.trk[1];
|
||||
|
||||
assert_eq!(trk.trkseg.len(), 2);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert_eq!(trkseg.len(), 19);
|
||||
let trkpt = &trkseg[0];
|
||||
assert_eq!(trkpt.coordinates.lat, 50.782212);
|
||||
assert_eq!(trkpt.coordinates.lng, 4.406377);
|
||||
assert_eq!(trkpt.ele, 115.5);
|
||||
|
||||
let trkseg = &trk.trkseg[1];
|
||||
assert_eq!(trkseg.len(), 10);
|
||||
let trkpt = &trkseg[0];
|
||||
assert_eq!(trkpt.coordinates.lat, 50.77906316558724);
|
||||
assert_eq!(trkpt.coordinates.lng, 4.412547477922485);
|
||||
assert_eq!(trkpt.ele, 133.3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_waypoint() {
|
||||
let mut f = File::open("data/with_waypoint.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.wpt.len(), 1);
|
||||
let chunk = &gpx.wpt[0];
|
||||
assert_eq!(chunk.wpt.len(), 1);
|
||||
let wpt = &chunk.wpt[0];
|
||||
assert_eq!(wpt.coordinates.lat, 50.7836710064975);
|
||||
assert_eq!(wpt.coordinates.lng, 4.410764082658738);
|
||||
assert!(wpt.name.as_ref().is_some_and(|n| n == "waypoint name"));
|
||||
assert!(wpt.cmt.as_ref().is_some_and(|c| c == "waypoint comment"));
|
||||
assert!(
|
||||
wpt.desc
|
||||
.as_ref()
|
||||
.is_some_and(|d| d == "waypoint description")
|
||||
);
|
||||
assert!(wpt.link.is_some());
|
||||
let link = wpt.link.as_ref().unwrap();
|
||||
assert_eq!(link.href, "https://gpx.studio");
|
||||
assert!(
|
||||
link.text
|
||||
.as_ref()
|
||||
.is_some_and(|t| t == "waypoint link text")
|
||||
);
|
||||
assert!(wpt.sym.as_ref().is_some_and(|s| s == "Bike Trail"));
|
||||
assert!(wpt.type_.as_ref().is_some_and(|t| t == "Bike Trail"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_trackpoint_time() {
|
||||
let mut f = File::open("data/with_time.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.trk.len(), 1);
|
||||
let trk = &gpx.trk[0];
|
||||
assert_eq!(trk.trkseg.len(), 1);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert!(trkseg.len() > 0);
|
||||
let trkpt = &trkseg[0];
|
||||
assert!(trkpt.time.is_some_and(|t| t == 1704063600000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_trackpoint_hr() {
|
||||
let mut f = File::open("data/with_hr.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.trk.len(), 1);
|
||||
let trk = &gpx.trk[0];
|
||||
assert_eq!(trk.trkseg.len(), 1);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert!(trkseg.len() > 0);
|
||||
let trkpt = &trkseg[0];
|
||||
assert!(trkpt.hr.is_some_and(|h| h == 150));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_trackpoint_cad() {
|
||||
let mut f = File::open("data/with_cad.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.trk.len(), 1);
|
||||
let trk = &gpx.trk[0];
|
||||
assert_eq!(trk.trkseg.len(), 1);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert!(trkseg.len() > 0);
|
||||
let trkpt = &trkseg[0];
|
||||
assert!(trkpt.cad.is_some_and(|c| c == 80));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_trackpoint_power_1() {
|
||||
let mut f = File::open("data/with_power_1.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.trk.len(), 1);
|
||||
let trk = &gpx.trk[0];
|
||||
assert_eq!(trk.trkseg.len(), 1);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert!(trkseg.len() > 0);
|
||||
let trkpt = &trkseg[0];
|
||||
assert!(trkpt.power.is_some_and(|p| p == 200));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_trackpoint_power_2() {
|
||||
let mut f = File::open("data/with_power_2.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.trk.len(), 1);
|
||||
let trk = &gpx.trk[0];
|
||||
assert_eq!(trk.trkseg.len(), 1);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert!(trkseg.len() > 0);
|
||||
let trkpt = &trkseg[0];
|
||||
assert!(trkpt.power.is_some_and(|p| p == 200));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_trackpoint_atemp() {
|
||||
let mut f = File::open("data/with_temp.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.trk.len(), 1);
|
||||
let trk = &gpx.trk[0];
|
||||
assert_eq!(trk.trkseg.len(), 1);
|
||||
let trkseg = &trk.trkseg[0];
|
||||
assert!(trkseg.len() > 0);
|
||||
let trkpt = &trkseg[0];
|
||||
assert!(trkpt.atemp.is_some_and(|t| t == 21));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_track_style() {
|
||||
let mut f = File::open("data/with_style.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
assert_eq!(gpx.trk.len(), 1);
|
||||
let trk = &gpx.trk[0];
|
||||
assert_eq!(trk.trkseg.len(), 1);
|
||||
assert!(trk.info.color.as_ref().is_some_and(|c| c == "#2d3ee9"));
|
||||
assert!(trk.info.opacity.is_some_and(|o| o == 0.5));
|
||||
assert!(trk.info.width.is_some_and(|w| w == 6.0));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
mod simplify;
|
||||
mod smooth;
|
||||
|
||||
pub use simplify::*;
|
||||
pub use smooth::*;
|
||||
@@ -0,0 +1,65 @@
|
||||
use crate::gpx::{TrackSegment, TrackSegmentIndex};
|
||||
|
||||
pub fn ramer_douglas_peucker<F, T>(
|
||||
trkseg: &TrackSegment,
|
||||
distance: &F,
|
||||
epsilon: T,
|
||||
) -> Vec<TrackSegmentIndex>
|
||||
where
|
||||
F: Fn(TrackSegmentIndex, TrackSegmentIndex, TrackSegmentIndex) -> T,
|
||||
T: Default + PartialOrd + Copy,
|
||||
{
|
||||
match trkseg.len() {
|
||||
0 => vec![],
|
||||
1 => vec![trkseg.first_index().unwrap()],
|
||||
2 => vec![trkseg.last_index().unwrap()],
|
||||
_ => {
|
||||
let first = trkseg.first_index().unwrap();
|
||||
let last = trkseg.last_index().unwrap();
|
||||
|
||||
let mut indices = vec![first];
|
||||
ramer_douglas_peucker_helper(trkseg, first, last, distance, epsilon, &mut indices);
|
||||
indices.push(last);
|
||||
indices
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ramer_douglas_peucker_helper<F, T>(
|
||||
trkseg: &TrackSegment,
|
||||
start: TrackSegmentIndex,
|
||||
end: TrackSegmentIndex,
|
||||
distance: &F,
|
||||
epsilon: T,
|
||||
indices: &mut Vec<TrackSegmentIndex>,
|
||||
) where
|
||||
F: Fn(TrackSegmentIndex, TrackSegmentIndex, TrackSegmentIndex) -> T,
|
||||
T: Default + PartialOrd + Copy,
|
||||
{
|
||||
let mut max_idx = None;
|
||||
let mut max_dist = T::default();
|
||||
|
||||
let mut cur = trkseg.next_index(Some(start));
|
||||
|
||||
while let Some(idx) = cur {
|
||||
if idx == end {
|
||||
break;
|
||||
}
|
||||
|
||||
let dist = distance(start, end, idx);
|
||||
if dist > max_dist {
|
||||
max_idx = Some(idx);
|
||||
max_dist = dist;
|
||||
}
|
||||
|
||||
cur = trkseg.next_index(cur);
|
||||
}
|
||||
|
||||
if let Some(idx) = max_idx {
|
||||
if max_dist > epsilon {
|
||||
ramer_douglas_peucker_helper(trkseg, start, idx, distance, epsilon, indices);
|
||||
indices.push(idx);
|
||||
ramer_douglas_peucker_helper(trkseg, idx, end, distance, epsilon, indices);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#[macro_export]
|
||||
macro_rules! for_each_window {
|
||||
(
|
||||
$trkseg:expr,
|
||||
$left:expr,
|
||||
$right:expr,
|
||||
$window:expr,
|
||||
|$a:ident, $b:ident| $distance:expr,
|
||||
|$i:ident, $l:ident, $r:ident| $body:block,
|
||||
) => {{
|
||||
let mut start = $left.unwrap_or_default();
|
||||
let mut cur = $left;
|
||||
while let Some(idx) = cur {
|
||||
// advance left if needed
|
||||
while start != idx && {
|
||||
let $a = start;
|
||||
let $b = idx;
|
||||
$distance
|
||||
} > $window {
|
||||
if let Some(next) = $trkseg.next_index(Some(start)) {
|
||||
if next == idx {
|
||||
break;
|
||||
}
|
||||
start = next;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// advance right if needed
|
||||
let mut end = idx;
|
||||
while let Some(next) = $trkseg.next_index(Some(end)) {
|
||||
if {
|
||||
let $a = idx;
|
||||
let $b = end;
|
||||
$distance
|
||||
} > $window {
|
||||
break;
|
||||
}
|
||||
end = next;
|
||||
}
|
||||
// apply body
|
||||
let $i = idx;
|
||||
let $l = start;
|
||||
let $r = end;
|
||||
$body
|
||||
// go next
|
||||
cur = $trkseg.next_index(cur);
|
||||
}
|
||||
}};
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use uuid::Uuid;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::{
|
||||
actions::parse,
|
||||
gpx::GPXFile,
|
||||
stack::{Stack, StackEntry},
|
||||
};
|
||||
|
||||
// Control flow
|
||||
// - get lock to cancel any other updates
|
||||
// - update files
|
||||
// - update separate statistics
|
||||
// - update selection
|
||||
// - update selection statistics
|
||||
// - notify UI (changed files, updated selection, new stats)
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct Controller {
|
||||
stack: Stack,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Controller {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
stack: Stack::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_file(&mut self, name: &str) {
|
||||
let mut file = GPXFile::default();
|
||||
file.info.name = name.to_string();
|
||||
self.stack.create_and_push_next(|entry: &mut StackEntry| {
|
||||
entry.insert(file.id, Rc::new(file));
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn load_file(&mut self, data: &[u8]) {
|
||||
if let Ok(file) = parse(data) {
|
||||
self.stack.create_and_push_next(|entry: &mut StackEntry| {
|
||||
entry.insert(file.id, Rc::new(file));
|
||||
true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn delete_file(&mut self, id: &[u8]) {
|
||||
if let Ok(id) = Uuid::from_slice(id) {
|
||||
self.stack
|
||||
.create_and_push_next(|entry: &mut StackEntry| entry.remove(&id).is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::gpx::{Trackpoint, Waypoint};
|
||||
|
||||
static MAX_TRKPT_CHUNK_SIZE: usize = 4096;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TrackpointChunk {
|
||||
pub trkpt: Vec<Trackpoint>,
|
||||
}
|
||||
|
||||
impl TrackpointChunk {
|
||||
pub fn is_full(&self) -> bool {
|
||||
self.trkpt.len() == MAX_TRKPT_CHUNK_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
static MAX_WPT_CHUNK_SIZE: usize = 128;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct WaypointChunk {
|
||||
pub wpt: Vec<Waypoint>,
|
||||
}
|
||||
|
||||
impl WaypointChunk {
|
||||
pub fn is_full(&self) -> bool {
|
||||
self.wpt.len() == MAX_WPT_CHUNK_SIZE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Link {
|
||||
pub href: String,
|
||||
pub text: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub struct LngLat {
|
||||
pub lng: f64,
|
||||
pub lat: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct LngLatBounds {
|
||||
pub sw: LngLat,
|
||||
pub ne: LngLat,
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gpx::{Link, Track, WaypointChunk};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GPXFile {
|
||||
pub id: Uuid,
|
||||
pub info: GPXFileInfo,
|
||||
pub trk: Vec<Track>,
|
||||
pub wpt: Vec<Rc<WaypointChunk>>,
|
||||
// TODO routes
|
||||
}
|
||||
|
||||
impl Default for GPXFile {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: Uuid::new_v4(),
|
||||
info: Default::default(),
|
||||
trk: Default::default(),
|
||||
wpt: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct GPXFileInfo {
|
||||
pub name: String,
|
||||
pub desc: Option<String>,
|
||||
pub author: Option<Author>,
|
||||
pub link: Option<Link>,
|
||||
pub time: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Author {
|
||||
pub name: Option<String>,
|
||||
pub email: Option<String>,
|
||||
pub link: Option<Link>,
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
mod chunk;
|
||||
mod common;
|
||||
mod file;
|
||||
mod segment;
|
||||
mod track;
|
||||
mod trackpoint;
|
||||
mod waypoint;
|
||||
|
||||
pub use chunk::*;
|
||||
pub use common::*;
|
||||
pub use file::*;
|
||||
pub use segment::*;
|
||||
pub use track::*;
|
||||
pub use trackpoint::*;
|
||||
pub use waypoint::*;
|
||||
@@ -0,0 +1,253 @@
|
||||
use std::{ops::Index, rc::Rc};
|
||||
|
||||
use crate::gpx::{Trackpoint, TrackpointChunk};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TrackSegment {
|
||||
chunks: Vec<Rc<TrackpointChunk>>,
|
||||
cumul_length: Vec<usize>,
|
||||
}
|
||||
|
||||
impl TrackSegment {
|
||||
pub fn push(&mut self, chunk: TrackpointChunk) {
|
||||
if chunk.trkpt.is_empty() {
|
||||
return;
|
||||
}
|
||||
self.cumul_length
|
||||
.push(self.cumul_length.last().copied().unwrap_or_default() + chunk.trkpt.len());
|
||||
self.chunks.push(Rc::new(chunk));
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.cumul_length.last().copied().unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> TrackSegmentIterator<'_> {
|
||||
TrackSegmentIterator::new(self)
|
||||
}
|
||||
|
||||
pub fn first_index(&self) -> Option<TrackSegmentIndex> {
|
||||
self.next_index(None)
|
||||
}
|
||||
|
||||
pub fn last_index(&self) -> Option<TrackSegmentIndex> {
|
||||
self.prev_index(None)
|
||||
}
|
||||
|
||||
pub fn next_index(&self, cur: Option<TrackSegmentIndex>) -> Option<TrackSegmentIndex> {
|
||||
let mut next = cur.map_or_default(|idx| TrackSegmentIndex {
|
||||
chunk: idx.chunk,
|
||||
pos: idx.pos + 1,
|
||||
});
|
||||
loop {
|
||||
if next.chunk >= self.chunks.len() {
|
||||
return None;
|
||||
}
|
||||
if next.pos == self.chunks[next.chunk].trkpt.len() {
|
||||
next.chunk += 1;
|
||||
next.pos = 0;
|
||||
} else {
|
||||
return Some(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prev_index(&self, cur: Option<TrackSegmentIndex>) -> Option<TrackSegmentIndex> {
|
||||
let mut prev = cur.unwrap_or(TrackSegmentIndex {
|
||||
chunk: self.chunks.len(),
|
||||
pos: 0,
|
||||
});
|
||||
loop {
|
||||
if prev.pos == 0 {
|
||||
if prev.chunk == 0 {
|
||||
return None;
|
||||
}
|
||||
prev.chunk -= 1;
|
||||
prev.pos = self.chunks[prev.chunk].trkpt.len();
|
||||
} else {
|
||||
prev.pos -= 1;
|
||||
return Some(prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_flat_index(&self, idx: TrackSegmentIndex) -> usize {
|
||||
idx.pos
|
||||
+ if idx.chunk > 0 {
|
||||
self.cumul_length[idx.chunk - 1]
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn locate(&self, idx: usize) -> Option<TrackSegmentIndex> {
|
||||
let chunk = self.cumul_length.partition_point(|l| idx >= *l);
|
||||
if chunk >= self.chunks.len() {
|
||||
return None;
|
||||
}
|
||||
let pos = if chunk > 0 {
|
||||
idx - self.cumul_length[chunk - 1]
|
||||
} else {
|
||||
idx
|
||||
};
|
||||
if pos >= self.chunks[chunk].trkpt.len() {
|
||||
None
|
||||
} else {
|
||||
Some(TrackSegmentIndex { chunk, pos })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<TrackSegmentIndex> for TrackSegment {
|
||||
type Output = Trackpoint;
|
||||
|
||||
fn index(&self, idx: TrackSegmentIndex) -> &Self::Output {
|
||||
&self.chunks[idx.chunk].trkpt[idx.pos]
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for TrackSegment {
|
||||
type Output = Trackpoint;
|
||||
|
||||
fn index(&self, idx: usize) -> &Self::Output {
|
||||
&self[self.locate(idx).unwrap()]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord)]
|
||||
pub struct TrackSegmentIndex {
|
||||
pub chunk: usize,
|
||||
pub pos: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TrackSegmentIterator<'a> {
|
||||
trkseg: &'a TrackSegment,
|
||||
idx: Option<TrackSegmentIndex>,
|
||||
}
|
||||
|
||||
impl<'a> TrackSegmentIterator<'a> {
|
||||
pub fn new(trkseg: &'a TrackSegment) -> Self {
|
||||
Self {
|
||||
trkseg,
|
||||
idx: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for TrackSegmentIterator<'a> {
|
||||
type Item = &'a Trackpoint;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.idx = self.trkseg.next_index(self.idx);
|
||||
self.idx.map(|idx| &self.trkseg[idx])
|
||||
}
|
||||
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
let idx = self
|
||||
.idx
|
||||
.map_or_default(|idx| self.trkseg.to_flat_index(idx))
|
||||
+ n;
|
||||
self.idx = self.trkseg.locate(idx);
|
||||
self.idx.map(|idx| &self.trkseg[idx])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::gpx::TrackpointChunk;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn create_track_segment(nb_chunks: usize) -> TrackSegment {
|
||||
let mut trkseg = TrackSegment::default();
|
||||
let mut count = 0;
|
||||
for n in 1..=nb_chunks {
|
||||
let mut chunk = TrackpointChunk::default();
|
||||
for _ in 0..n {
|
||||
let mut trkpt = Trackpoint::default();
|
||||
trkpt.ele = count as f64;
|
||||
chunk.trkpt.push(trkpt);
|
||||
count += 1;
|
||||
}
|
||||
trkseg.push(chunk);
|
||||
}
|
||||
trkseg
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_len() {
|
||||
let nb_chunks = 10;
|
||||
let trkseg = create_track_segment(nb_chunks);
|
||||
assert_eq!(trkseg.len(), nb_chunks * (nb_chunks + 1) / 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_locate() {
|
||||
let nb_chunks = 10;
|
||||
let trkseg = create_track_segment(nb_chunks);
|
||||
for i in 0..trkseg.len() {
|
||||
let idx = trkseg.locate(i);
|
||||
assert!(idx.is_some());
|
||||
assert_eq!(trkseg[idx.unwrap()].ele, i as f64);
|
||||
}
|
||||
|
||||
assert!(trkseg.locate(trkseg.len()).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_index() {
|
||||
let nb_chunks = 10;
|
||||
let trkseg = create_track_segment(nb_chunks);
|
||||
for i in 0..trkseg.len() {
|
||||
assert_eq!(trkseg[i].ele, i as f64);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_index_out_of_bounds_1() {
|
||||
let nb_chunks = 10;
|
||||
let trkseg = create_track_segment(nb_chunks);
|
||||
trkseg[trkseg.len()].ele;
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_index_out_of_bounds_2() {
|
||||
let nb_chunks = 10;
|
||||
let trkseg = create_track_segment(nb_chunks);
|
||||
trkseg[TrackSegmentIndex {
|
||||
chunk: trkseg.chunks.len(),
|
||||
pos: 0,
|
||||
}]
|
||||
.ele;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter() {
|
||||
let nb_chunks = 10;
|
||||
let trkseg = create_track_segment(nb_chunks);
|
||||
for (i, trkpt) in trkseg.iter().enumerate() {
|
||||
assert!(std::ptr::eq(&trkseg[i], trkpt));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_nth() {
|
||||
let nb_chunks = 10;
|
||||
let trkseg = create_track_segment(nb_chunks);
|
||||
let tenth = trkseg.iter().nth(10);
|
||||
assert!(tenth.is_some());
|
||||
assert!(std::ptr::eq(&trkseg[10], tenth.unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_skip() {
|
||||
let nb_chunks = 10;
|
||||
let trkseg = create_track_segment(nb_chunks);
|
||||
for (i, trkpt) in trkseg.iter().enumerate().skip(5) {
|
||||
assert!(std::ptr::eq(&trkseg[i], trkpt));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
use crate::gpx::{Link, TrackSegment};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Track {
|
||||
pub info: TrackInfo,
|
||||
pub trkseg: Vec<TrackSegment>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TrackInfo {
|
||||
pub name: Option<String>,
|
||||
pub cmt: Option<String>,
|
||||
pub desc: Option<String>,
|
||||
pub src: Option<String>,
|
||||
pub link: Option<Link>,
|
||||
pub type_: Option<String>,
|
||||
pub color: Option<String>,
|
||||
pub opacity: Option<f64>,
|
||||
pub width: Option<f64>,
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
use crate::gpx::LngLat;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Trackpoint {
|
||||
pub coordinates: LngLat,
|
||||
pub ele: f64,
|
||||
pub time: Option<i64>,
|
||||
pub atemp: Option<i16>,
|
||||
pub hr: Option<u16>,
|
||||
pub cad: Option<u16>,
|
||||
pub power: Option<u16>,
|
||||
// TODO OSM data? or store intervals at a higher level?
|
||||
}
|
||||
|
||||
impl Trackpoint {
|
||||
pub fn time_diff(&self, other: &Trackpoint) -> Option<i64> {
|
||||
self.time.zip(other.time).map(|(t1, t2)| t1 - t2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
use crate::gpx::{Link, LngLat};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Waypoint {
|
||||
pub coordinates: LngLat,
|
||||
pub ele: f64,
|
||||
pub time: Option<i64>,
|
||||
pub name: Option<String>,
|
||||
pub cmt: Option<String>,
|
||||
pub desc: Option<String>,
|
||||
pub link: Option<Link>,
|
||||
pub sym: Option<String>,
|
||||
pub type_: Option<String>,
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
mod actions;
|
||||
mod controller;
|
||||
mod gpx;
|
||||
mod stack;
|
||||
mod statistics;
|
||||
mod utils;
|
||||
mod algorithms;
|
||||
@@ -0,0 +1,100 @@
|
||||
use std::{collections::HashMap, rc::Rc};
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gpx::GPXFile;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Stack {
|
||||
entries: Vec<StackEntry>,
|
||||
index: Option<usize>,
|
||||
}
|
||||
|
||||
impl Stack {
|
||||
pub fn current(&self) -> Option<&StackEntry> {
|
||||
match self.index {
|
||||
Some(i) => Some(&self.entries[i]),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_and_push_next<F>(&mut self, f: F)
|
||||
where
|
||||
F: FnOnce(&mut StackEntry) -> bool,
|
||||
{
|
||||
let mut next = self.current().map_or_default(|c| c.clone());
|
||||
if f(&mut next) {
|
||||
self.push(next);
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn update(&mut self, files: &[Rc<GPXFile>], ids: &[GPXFileId]) {
|
||||
// let mut next = match self.current() {
|
||||
// Some(current) => current.clone(),
|
||||
// None => StackEntry::default(),
|
||||
// };
|
||||
// for (file, id) in files.iter().zip(ids) {
|
||||
// next.insert(*id, file.clone());
|
||||
// }
|
||||
// self.push(next);
|
||||
// }
|
||||
|
||||
// pub fn delete(&mut self, files: &[GPXFileId]) {
|
||||
// if let Some(current) = self.current() {
|
||||
// let mut next = current.clone();
|
||||
// for file in files {
|
||||
// next.remove(file);
|
||||
// }
|
||||
// self.push(next);
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn can_undo(&self) -> bool {
|
||||
self.index.is_some()
|
||||
}
|
||||
|
||||
pub fn can_redo(&self) -> bool {
|
||||
match self.index {
|
||||
Some(i) => i + 1 < self.entries.len(),
|
||||
None => !self.entries.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn undo(&mut self) {
|
||||
if let Some(i) = self.index {
|
||||
if i == 0 {
|
||||
self.index = None;
|
||||
} else {
|
||||
self.index = Some(i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn redo(&mut self) {
|
||||
match self.index {
|
||||
Some(i) => {
|
||||
if i + 1 < self.entries.len() {
|
||||
self.index = Some(i + 1);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if !self.entries.is_empty() {
|
||||
self.index = Some(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn push(&mut self, entry: StackEntry) {
|
||||
if let Some(i) = self.index {
|
||||
if i + 1 < self.entries.len() {
|
||||
self.entries.truncate(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
self.entries.push(entry);
|
||||
self.index = Some(self.entries.len() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub type StackEntry = HashMap<Uuid, Rc<GPXFile>>;
|
||||
@@ -0,0 +1,292 @@
|
||||
use crate::{
|
||||
algorithms::ramer_douglas_peucker,
|
||||
for_each_window,
|
||||
gpx::{LngLat, LngLatBounds, TrackSegment, Trackpoint},
|
||||
utils::{distance, slope, speed},
|
||||
};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct GPXStatistics {
|
||||
pub total_distance: f64,
|
||||
pub moving_distance: Option<f64>,
|
||||
pub moving_time: Option<i64>,
|
||||
pub elevation_gain: f64,
|
||||
pub elevation_loss: f64,
|
||||
pub start_time: Option<i64>,
|
||||
pub end_time: Option<i64>,
|
||||
pub bounds: LngLatBounds,
|
||||
pub local: Vec<TrackpointStatistics>,
|
||||
}
|
||||
|
||||
impl GPXStatistics {
|
||||
pub fn total_time(&self) -> Option<i64> {
|
||||
self.start_time.zip(self.end_time).map(|(t1, t2)| t2 - t1)
|
||||
}
|
||||
|
||||
pub fn total_speed(&self) -> Option<f64> {
|
||||
self.total_time().map(|t| speed(self.total_distance, t))
|
||||
}
|
||||
|
||||
pub fn moving_speed(&self) -> Option<f64> {
|
||||
self.moving_distance
|
||||
.zip(self.moving_time)
|
||||
.map(|(d, t)| speed(d, t))
|
||||
}
|
||||
|
||||
pub fn compute(trkseg: &TrackSegment) -> Self {
|
||||
let mut stats = Self::default();
|
||||
if trkseg.len() == 0 {
|
||||
return stats;
|
||||
}
|
||||
|
||||
let mut prev = &trkseg[0];
|
||||
for cur in trkseg.iter() {
|
||||
stats.accumulate(prev, cur);
|
||||
prev = cur;
|
||||
}
|
||||
|
||||
stats.compute_smoothed_speed(trkseg);
|
||||
stats.compute_smoothed_elevation_gain(trkseg);
|
||||
|
||||
stats
|
||||
}
|
||||
|
||||
fn accumulate(&mut self, prev: &Trackpoint, cur: &Trackpoint) {
|
||||
self.accumulate_distance_and_time(prev, cur);
|
||||
self.update_time_bounds(cur.time);
|
||||
self.update_bounds(&cur.coordinates);
|
||||
self.local
|
||||
.push(TrackpointStatistics::from_partial_stats(&self));
|
||||
}
|
||||
|
||||
fn accumulate_distance_and_time(&mut self, prev: &Trackpoint, cur: &Trackpoint) {
|
||||
let dist = distance(prev.coordinates, cur.coordinates);
|
||||
let time = cur.time_diff(prev);
|
||||
|
||||
self.total_distance += dist;
|
||||
|
||||
if let Some(time) = time {
|
||||
let speed = speed(dist, time);
|
||||
if speed >= 0.5 && speed <= 1500.0 {
|
||||
self.moving_distance = self.moving_distance.map_or(Some(dist), |d| Some(d + dist));
|
||||
self.moving_time = self.moving_time.map_or(Some(time), |t| Some(t + time));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_time_bounds(&mut self, time: Option<i64>) {
|
||||
if let Some(time) = time {
|
||||
if self.start_time.is_none() {
|
||||
self.start_time = Some(time);
|
||||
}
|
||||
self.end_time = Some(time);
|
||||
}
|
||||
}
|
||||
|
||||
fn update_bounds(&mut self, coordinates: &LngLat) {
|
||||
self.bounds.sw.lng = self.bounds.sw.lng.min(coordinates.lng);
|
||||
self.bounds.sw.lat = self.bounds.sw.lat.min(coordinates.lat);
|
||||
self.bounds.ne.lng = self.bounds.ne.lng.min(coordinates.lng);
|
||||
self.bounds.ne.lat = self.bounds.ne.lat.min(coordinates.lat);
|
||||
}
|
||||
|
||||
fn compute_smoothed_speed(&mut self, trkseg: &TrackSegment) {
|
||||
for_each_window!(
|
||||
trkseg,
|
||||
trkseg.first_index(),
|
||||
trkseg.last_index(),
|
||||
Some(10000),
|
||||
|i, j| trkseg[i].time_diff(&trkseg[j]),
|
||||
|i, left, right| {
|
||||
let i = trkseg.to_flat_index(i);
|
||||
let left = trkseg.to_flat_index(left);
|
||||
let right = trkseg.to_flat_index(right);
|
||||
self.local[i].speed = trkseg[right].time_diff(&trkseg[left]).map(|t| {
|
||||
speed(
|
||||
self.local[right].total_distance - self.local[left].total_distance,
|
||||
t,
|
||||
)
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn compute_smoothed_elevation_gain(&mut self, trkseg: &TrackSegment) {
|
||||
let simplified = ramer_douglas_peucker(
|
||||
trkseg,
|
||||
&|i, j, k| {
|
||||
let x1 = self.local[trkseg.to_flat_index(i)].total_distance * 1000.0;
|
||||
let x2 = self.local[trkseg.to_flat_index(j)].total_distance * 1000.0;
|
||||
let x3 = self.local[trkseg.to_flat_index(k)].total_distance * 1000.0;
|
||||
let y1 = trkseg[i].ele;
|
||||
let y2 = trkseg[j].ele;
|
||||
let y3 = trkseg[k].ele;
|
||||
|
||||
let dist = ((y2 - y1).powi(2) + (x2 - x1).powi(2)).sqrt();
|
||||
if dist == 0.0 {
|
||||
((x3 - x1).powi(2) + (y3 - y1).powi(2)).sqrt()
|
||||
} else {
|
||||
((y2 - y1) * x3 - (x2 - x1) * y3 + x2 * y1 - y2 * x1).abs() / dist
|
||||
}
|
||||
},
|
||||
20.0,
|
||||
);
|
||||
|
||||
for i in 0..(simplified.len() - 1) {
|
||||
let start = simplified[i];
|
||||
let end = simplified[i + 1];
|
||||
let last = i + 1 == simplified.len() - 1;
|
||||
|
||||
let mut cumul_ele = 0.0;
|
||||
let mut current_left = start;
|
||||
let mut current_right = Some(start);
|
||||
let mut prev_smoothed_ele = trkseg[start].ele;
|
||||
|
||||
for_each_window!(
|
||||
trkseg,
|
||||
Some(start),
|
||||
Some(end),
|
||||
0.1,
|
||||
|i, j| {
|
||||
let i = trkseg.to_flat_index(i);
|
||||
let j = trkseg.to_flat_index(j);
|
||||
self.local[j].total_distance - self.local[i].total_distance
|
||||
},
|
||||
|i, left, right| {
|
||||
while current_left != left {
|
||||
cumul_ele -= trkseg[current_left].ele;
|
||||
current_left = trkseg.next_index(Some(current_left)).unwrap();
|
||||
}
|
||||
while let Some(current) = current_right {
|
||||
if current > right {
|
||||
break;
|
||||
}
|
||||
cumul_ele += trkseg[current].ele;
|
||||
current_right = trkseg.next_index(current_right);
|
||||
}
|
||||
|
||||
let flat_i = trkseg.to_flat_index(i);
|
||||
let flat_left = trkseg.to_flat_index(left);
|
||||
let flat_right = trkseg.to_flat_index(right);
|
||||
|
||||
let smoothed_ele: f64 = if i == start || i == end {
|
||||
trkseg[i].ele
|
||||
} else {
|
||||
cumul_ele / (flat_right - flat_left + 1) as f64
|
||||
};
|
||||
|
||||
let delta = smoothed_ele - prev_smoothed_ele;
|
||||
if delta > 0.0 {
|
||||
self.elevation_gain += delta;
|
||||
} else if delta < 0.0 {
|
||||
self.elevation_loss -= delta;
|
||||
}
|
||||
|
||||
if i < end || last {
|
||||
self.local[flat_i].elevation_gain = self.elevation_gain;
|
||||
self.local[flat_i].elevation_loss = self.elevation_loss;
|
||||
}
|
||||
|
||||
prev_smoothed_ele = smoothed_ele;
|
||||
},
|
||||
);
|
||||
|
||||
let flat_start = trkseg.to_flat_index(start);
|
||||
let flat_end = trkseg.to_flat_index(end);
|
||||
|
||||
let segment_dist =
|
||||
self.local[flat_end].total_distance - self.local[flat_start].total_distance;
|
||||
let segment_ele = trkseg[end].ele - trkseg[start].ele;
|
||||
let segment_slope = slope(segment_ele, segment_dist);
|
||||
for k in flat_start..(flat_end + last as usize) {
|
||||
self.local[k].slope_segment = SlopeSegment {
|
||||
slope: segment_slope,
|
||||
distance: segment_dist,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
for_each_window!(
|
||||
trkseg,
|
||||
trkseg.first_index(),
|
||||
trkseg.last_index(),
|
||||
0.05,
|
||||
|i, j| {
|
||||
let i = trkseg.to_flat_index(i);
|
||||
let j = trkseg.to_flat_index(j);
|
||||
self.local[j].total_distance - self.local[i].total_distance
|
||||
},
|
||||
|i, left, right| {
|
||||
let flat_i = trkseg.to_flat_index(i);
|
||||
let flat_left = trkseg.to_flat_index(left);
|
||||
let flat_right = trkseg.to_flat_index(right);
|
||||
let dist =
|
||||
self.local[flat_right].total_distance - self.local[flat_left].total_distance;
|
||||
let ele = trkseg[right].ele - trkseg[left].ele;
|
||||
self.local[flat_i].slope = slope(ele, dist);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct SlopeSegment {
|
||||
pub slope: f64,
|
||||
pub distance: f64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TrackpointStatistics {
|
||||
pub total_distance: f64,
|
||||
pub moving_distance: Option<f64>,
|
||||
pub total_time: Option<i64>,
|
||||
pub moving_time: Option<i64>,
|
||||
pub speed: Option<f64>,
|
||||
pub elevation_gain: f64,
|
||||
pub elevation_loss: f64,
|
||||
pub slope: f64,
|
||||
pub slope_segment: SlopeSegment,
|
||||
}
|
||||
|
||||
impl TrackpointStatistics {
|
||||
fn from_partial_stats(stats: &GPXStatistics) -> Self {
|
||||
Self {
|
||||
total_distance: stats.total_distance,
|
||||
moving_distance: stats.moving_distance,
|
||||
total_time: stats.start_time.zip(stats.end_time).map(|(t1, t2)| t2 - t1),
|
||||
moving_time: stats.moving_time,
|
||||
speed: None,
|
||||
elevation_gain: stats.elevation_gain,
|
||||
elevation_loss: stats.elevation_loss,
|
||||
slope: Default::default(),
|
||||
slope_segment: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{fs::File, io::Read};
|
||||
|
||||
use crate::actions::parse;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_compute_smoothed_speed() {
|
||||
let mut f = File::open("data/with_time.gpx").unwrap();
|
||||
let mut data = String::new();
|
||||
let _ = f.read_to_string(&mut data);
|
||||
let gpx = parse(data.as_bytes()).unwrap();
|
||||
|
||||
let trkseg = &gpx.trk[0].trkseg[0];
|
||||
let stats = GPXStatistics::compute(trkseg);
|
||||
assert_eq!(stats.local.len(), trkseg.len());
|
||||
for trkpt_stats in stats.local.iter() {
|
||||
assert!(trkpt_stats.speed.is_some());
|
||||
let speed = trkpt_stats.speed.unwrap();
|
||||
assert_ne!(speed, f64::NAN);
|
||||
assert!((speed - 20.0).abs() < 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
use std::f64::consts::PI;
|
||||
|
||||
use crate::gpx::LngLat;
|
||||
|
||||
static TO_RADIANS: f64 = PI / 180.0;
|
||||
static EARTH_RADIUS: f64 = 6371.0088;
|
||||
|
||||
/// Computes the distance in kilometers between two coordinates using the Haversine formula
|
||||
pub fn distance(p1: LngLat, p2: LngLat) -> f64 {
|
||||
let lat1 = p1.lat * TO_RADIANS;
|
||||
let lat2 = p2.lat * TO_RADIANS;
|
||||
let delta_lat = lat2 - lat1;
|
||||
let delta_lng = (p2.lng - p1.lng) * TO_RADIANS;
|
||||
|
||||
let a =
|
||||
(delta_lat / 2.0).sin().powi(2) + lat1.cos() * lat2.cos() * (delta_lng / 2.0).sin().powi(2);
|
||||
let c = 2.0 * a.min(1.0).sqrt().asin();
|
||||
EARTH_RADIUS * c
|
||||
}
|
||||
|
||||
/// Computes the speed for a given distance in kilometers and a time in milliseconds
|
||||
pub fn speed(distance: f64, time: i64) -> f64 {
|
||||
distance / (time as f64 / 3600_000.0)
|
||||
}
|
||||
|
||||
pub fn slope(ele: f64, distance: f64) -> f64 {
|
||||
if distance == 0.0 {
|
||||
100.0
|
||||
} else {
|
||||
0.1 * ele / distance
|
||||
}
|
||||
}
|
||||
|
||||
static METERS_PER_LATITUDE_DEGREE: f64 = 111320.0;
|
||||
|
||||
fn get_meters_per_longitude_degree(latitude: f64) -> f64 {
|
||||
((latitude * PI) / 180.0).cos() * METERS_PER_LATITUDE_DEGREE
|
||||
}
|
||||
|
||||
// Calculates the point on the line segment defined by p1 and p2
|
||||
// that is closest to the third point, p3.
|
||||
// Uses simple planar geometry (ignores earth curvature).
|
||||
fn projected(p1: LngLat, p2: LngLat, coord3: LngLat) -> LngLat {
|
||||
// Convert to meters using approximate scaling
|
||||
let meters_per_longitude_degree = get_meters_per_longitude_degree(p1.lat);
|
||||
|
||||
let x1 = p1.lng * meters_per_longitude_degree;
|
||||
let y1 = p1.lat * METERS_PER_LATITUDE_DEGREE;
|
||||
let x2 = p2.lng * meters_per_longitude_degree;
|
||||
let y2 = p2.lat * METERS_PER_LATITUDE_DEGREE;
|
||||
let x3 = coord3.lng * meters_per_longitude_degree;
|
||||
let y3 = coord3.lat * METERS_PER_LATITUDE_DEGREE;
|
||||
|
||||
let dx = x2 - x1;
|
||||
let dy = y2 - y1;
|
||||
let segment_length_squared = dx * dx + dy * dy;
|
||||
|
||||
if segment_length_squared == 0.0 {
|
||||
// p1 and p2 are the same point
|
||||
p1
|
||||
} else {
|
||||
// Project p3 onto the line defined by p1-p2
|
||||
let t =
|
||||
0.0_f64.max(1.0_f64.min(((x3 - x1) * dx + (y3 - y1) * dy) / segment_length_squared));
|
||||
|
||||
// Find the closest point on the segment
|
||||
let proj_x = x1 + t * dx;
|
||||
let proj_y = y1 + t * dy;
|
||||
|
||||
// Convert back to degrees
|
||||
LngLat {
|
||||
lng: proj_x / meters_per_longitude_degree,
|
||||
lat: proj_y / METERS_PER_LATITUDE_DEGREE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the perpendicular distance in meters
|
||||
/// between a line segment (defined by p1 and p2) and a third point, p3.
|
||||
/// Uses simple planar geometry (ignores earth curvature).
|
||||
fn crossarc(p1: LngLat, p2: LngLat, p3: LngLat) -> f64 {
|
||||
// Convert to meters using approximate scaling
|
||||
let meters_per_longitude_degree = get_meters_per_longitude_degree(p1.lat);
|
||||
|
||||
let x1 = p1.lng * meters_per_longitude_degree;
|
||||
let y1 = p1.lat * METERS_PER_LATITUDE_DEGREE;
|
||||
let x2 = p2.lng * meters_per_longitude_degree;
|
||||
let y2 = p2.lat * METERS_PER_LATITUDE_DEGREE;
|
||||
let x3 = p3.lng * meters_per_longitude_degree;
|
||||
let y3 = p3.lat * METERS_PER_LATITUDE_DEGREE;
|
||||
|
||||
let dx = x2 - x1;
|
||||
let dy = y2 - y1;
|
||||
let segment_length_squared = dx * dx + dy * dy;
|
||||
|
||||
if segment_length_squared == 0.0 {
|
||||
// p1 and p2 are the same point
|
||||
((x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1)).sqrt()
|
||||
} else {
|
||||
// Project p3 onto the line defined by p1 - p2
|
||||
let t =
|
||||
0.0_f64.max(1.0_f64.min(((x3 - x1) * dx + (y3 - y1) * dy) / segment_length_squared));
|
||||
|
||||
// Find the closest point on the segment
|
||||
let proj_x = x1 + t * dx;
|
||||
let proj_y = y1 + t * dy;
|
||||
|
||||
// Return distance from p3 to the projected point
|
||||
((x3 - proj_x) * (x3 - proj_x) + (y3 - proj_y) * (y3 - proj_y)).sqrt()
|
||||
}
|
||||
}
|
||||
@@ -12,16 +12,20 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"fast-xml-parser": "^4.5.0",
|
||||
"immer": "^10.1.1",
|
||||
"ts-node": "^10.9.2"
|
||||
"immer": "^10.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/geojson": "^7946.0.14",
|
||||
"@types/node": "^20.16.10",
|
||||
"@typescript-eslint/parser": "^8.22.0",
|
||||
"prettier": "^3.4.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"postinstall": "npm run build"
|
||||
"postinstall": "npm run build",
|
||||
"lint": "prettier --check . --config ../.prettierrc && eslint .",
|
||||
"format": "prettier --write . --config ../.prettierrc"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export * from './gpx';
|
||||
export * from './statistics';
|
||||
export { Coordinates, LineStyleExtension, WaypointType } from './types';
|
||||
export { parseGPX, buildGPX } from './io';
|
||||
export * from './simplify';
|
||||
|
||||
|
||||
@@ -1,25 +1,68 @@
|
||||
import { XMLParser, XMLBuilder } from "fast-xml-parser";
|
||||
import { GPXFileType } from "./types";
|
||||
import { GPXFile } from "./gpx";
|
||||
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
|
||||
import { GPXFileType } from './types';
|
||||
import { GPXFile } from './gpx';
|
||||
|
||||
const attributesWithNamespace = {
|
||||
RoutePointExtension: 'gpxx:RoutePointExtension',
|
||||
rpt: 'gpxx:rpt',
|
||||
TrackPointExtension: 'gpxtpx:TrackPointExtension',
|
||||
PowerExtension: 'gpxpx:PowerExtension',
|
||||
atemp: 'gpxtpx:atemp',
|
||||
hr: 'gpxtpx:hr',
|
||||
cad: 'gpxtpx:cad',
|
||||
Extensions: 'gpxtpx:Extensions',
|
||||
PowerInWatts: 'gpxpx:PowerInWatts',
|
||||
power: 'gpxpx:PowerExtension',
|
||||
line: 'gpx_style:line',
|
||||
color: 'gpx_style:color',
|
||||
opacity: 'gpx_style:opacity',
|
||||
width: 'gpx_style:width',
|
||||
};
|
||||
|
||||
const floatPatterns = [
|
||||
/[-+]?\d*\.\d+$/, // decimal
|
||||
/[-+]?\d+$/, // integer
|
||||
];
|
||||
function safeParseFloat(value: string): number {
|
||||
const parsed = parseFloat(value);
|
||||
if (!isNaN(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
for (const pattern of floatPatterns) {
|
||||
const match = value.match(pattern);
|
||||
if (match) {
|
||||
return parseFloat(match[0]);
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
export function parseGPX(gpxData: string): GPXFile {
|
||||
const parser = new XMLParser({
|
||||
ignoreAttributes: false,
|
||||
attributeNamePrefix: "",
|
||||
attributeNamePrefix: '',
|
||||
attributesGroupName: 'attributes',
|
||||
removeNSPrefix: true,
|
||||
isArray(name: string) {
|
||||
return name === 'trk' || name === 'trkseg' || name === 'trkpt' || name === 'wpt' || name === 'rte' || name === 'rtept' || name === 'gpxx:rpt';
|
||||
return (
|
||||
name === 'trk' ||
|
||||
name === 'trkseg' ||
|
||||
name === 'trkpt' ||
|
||||
name === 'wpt' ||
|
||||
name === 'rte' ||
|
||||
name === 'rtept' ||
|
||||
name === 'gpxx:rpt'
|
||||
);
|
||||
},
|
||||
attributeValueProcessor(attrName, attrValue, jPath) {
|
||||
if (attrName === 'lat' || attrName === 'lon') {
|
||||
return parseFloat(attrValue);
|
||||
return safeParseFloat(attrValue);
|
||||
}
|
||||
return attrValue;
|
||||
},
|
||||
transformTagName(tagName: string) {
|
||||
if (tagName === 'power') {
|
||||
// Transform the simple <power> tag to the more complex <gpxpx:PowerExtension> tag, the nested <gpxpx:PowerInWatts> tag is then handled by the tagValueProcessor
|
||||
return 'gpxpx:PowerExtension';
|
||||
if (attributesWithNamespace[tagName]) {
|
||||
return attributesWithNamespace[tagName];
|
||||
}
|
||||
return tagName;
|
||||
},
|
||||
@@ -27,22 +70,29 @@ export function parseGPX(gpxData: string): GPXFile {
|
||||
tagValueProcessor(tagName, tagValue, jPath, hasAttributes, isLeafNode) {
|
||||
if (isLeafNode) {
|
||||
if (tagName === 'ele') {
|
||||
return parseFloat(tagValue);
|
||||
return safeParseFloat(tagValue);
|
||||
}
|
||||
|
||||
if (tagName === 'time') {
|
||||
return new Date(tagValue);
|
||||
}
|
||||
|
||||
if (tagName === 'gpxtpx:atemp' || tagName === 'gpxtpx:hr' || tagName === 'gpxtpx:cad' || tagName === 'gpxpx:PowerInWatts' || tagName === 'opacity' || tagName === 'weight') {
|
||||
return parseFloat(tagValue);
|
||||
if (
|
||||
tagName === 'gpxtpx:atemp' ||
|
||||
tagName === 'gpxtpx:hr' ||
|
||||
tagName === 'gpxtpx:cad' ||
|
||||
tagName === 'gpxpx:PowerInWatts' ||
|
||||
tagName === 'gpx_style:opacity' ||
|
||||
tagName === 'gpx_style:width'
|
||||
) {
|
||||
return safeParseFloat(tagValue);
|
||||
}
|
||||
|
||||
if (tagName === 'gpxpx:PowerExtension') {
|
||||
// Finish the transformation of the simple <power> tag to the more complex <gpxpx:PowerExtension> tag
|
||||
// Note that this only targets the transformed <power> tag, since it must be a leaf node
|
||||
return {
|
||||
'gpxpx:PowerInWatts': parseFloat(tagValue)
|
||||
'gpxpx:PowerInWatts': safeParseFloat(tagValue),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -54,7 +104,7 @@ export function parseGPX(gpxData: string): GPXFile {
|
||||
const parsed: GPXFileType = parser.parse(gpxData).gpx;
|
||||
|
||||
// @ts-ignore
|
||||
if (parsed.metadata === "") {
|
||||
if (parsed.metadata === '') {
|
||||
parsed.metadata = {};
|
||||
}
|
||||
|
||||
@@ -64,25 +114,32 @@ export function parseGPX(gpxData: string): GPXFile {
|
||||
export function buildGPX(file: GPXFile, exclude: string[]): string {
|
||||
const gpx = file.toGPXFileType(exclude);
|
||||
|
||||
let lastDate = undefined;
|
||||
const builder = new XMLBuilder({
|
||||
format: true,
|
||||
ignoreAttributes: false,
|
||||
attributeNamePrefix: "",
|
||||
attributeNamePrefix: '',
|
||||
attributesGroupName: 'attributes',
|
||||
suppressEmptyNode: true,
|
||||
tagValueProcessor: (tagName: string, tagValue: unknown): string => {
|
||||
tagValueProcessor: (tagName: string, tagValue: unknown): string | undefined => {
|
||||
if (tagValue instanceof Date) {
|
||||
if (isNaN(tagValue.getTime())) {
|
||||
return lastDate?.toISOString();
|
||||
}
|
||||
lastDate = tagValue;
|
||||
return tagValue.toISOString();
|
||||
}
|
||||
return tagValue.toString();
|
||||
},
|
||||
});
|
||||
|
||||
gpx.attributes.creator = gpx.attributes.creator ?? 'https://gpx.studio';
|
||||
if (!gpx.attributes) gpx.attributes = {};
|
||||
gpx.attributes['creator'] = gpx.attributes['creator'] ?? 'https://gpx.studio';
|
||||
gpx.attributes['version'] = '1.1';
|
||||
gpx.attributes['xmlns'] = 'http://www.topografix.com/GPX/1/1';
|
||||
gpx.attributes['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance';
|
||||
gpx.attributes['xsi:schemaLocation'] = 'http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/PowerExtension/v1 http://www.garmin.com/xmlschemas/PowerExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd';
|
||||
gpx.attributes['xsi:schemaLocation'] =
|
||||
'http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/PowerExtension/v1 http://www.garmin.com/xmlschemas/PowerExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd';
|
||||
gpx.attributes['xmlns:gpxtpx'] = 'http://www.garmin.com/xmlschemas/TrackPointExtension/v1';
|
||||
gpx.attributes['xmlns:gpxx'] = 'http://www.garmin.com/xmlschemas/GpxExtensions/v3';
|
||||
gpx.attributes['xmlns:gpxpx'] = 'http://www.garmin.com/xmlschemas/PowerExtension/v1';
|
||||
@@ -93,19 +150,24 @@ export function buildGPX(file: GPXFile, exclude: string[]): string {
|
||||
}
|
||||
|
||||
return builder.build({
|
||||
"?xml": {
|
||||
'?xml': {
|
||||
attributes: {
|
||||
version: "1.0",
|
||||
encoding: "UTF-8",
|
||||
}
|
||||
version: '1.0',
|
||||
encoding: 'UTF-8',
|
||||
},
|
||||
gpx: removeEmptyElements(gpx)
|
||||
},
|
||||
gpx: removeEmptyElements(gpx),
|
||||
});
|
||||
}
|
||||
|
||||
function removeEmptyElements(obj: GPXFileType): GPXFileType {
|
||||
for (const key in obj) {
|
||||
if (obj[key] === null || obj[key] === undefined || obj[key] === '' || (Array.isArray(obj[key]) && obj[key].length === 0)) {
|
||||
if (
|
||||
obj[key] === null ||
|
||||
obj[key] === undefined ||
|
||||
obj[key] === '' ||
|
||||
(Array.isArray(obj[key]) && obj[key].length === 0)
|
||||
) {
|
||||
delete obj[key];
|
||||
} else if (typeof obj[key] === 'object' && !(obj[key] instanceof Date)) {
|
||||
removeEmptyElements(obj[key]);
|
||||
|
||||
@@ -1,33 +1,46 @@
|
||||
import { TrackPoint } from "./gpx";
|
||||
import { Coordinates } from "./types";
|
||||
import { TrackPoint } from './gpx';
|
||||
import { Coordinates } from './types';
|
||||
|
||||
export type SimplifiedTrackPoint = { point: TrackPoint, distance?: number };
|
||||
export type SimplifiedTrackPoint = { point: TrackPoint; distance?: number };
|
||||
|
||||
const earthRadius = 6371008.8;
|
||||
|
||||
export function ramerDouglasPeucker(points: TrackPoint[], epsilon: number = 50, measure: (a: TrackPoint, b: TrackPoint, c: TrackPoint) => number = crossarcDistance): SimplifiedTrackPoint[] {
|
||||
export function ramerDouglasPeucker(
|
||||
points: TrackPoint[],
|
||||
epsilon: number = 50,
|
||||
measure: (a: TrackPoint, b: TrackPoint, c: TrackPoint) => number = crossarcDistance
|
||||
): SimplifiedTrackPoint[] {
|
||||
if (points.length == 0) {
|
||||
return [];
|
||||
} else if (points.length == 1) {
|
||||
return [{
|
||||
point: points[0]
|
||||
}];
|
||||
return [
|
||||
{
|
||||
point: points[0],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
let simplified = [{
|
||||
point: points[0]
|
||||
}];
|
||||
let simplified = [
|
||||
{
|
||||
point: points[0],
|
||||
},
|
||||
];
|
||||
ramerDouglasPeuckerRecursive(points, epsilon, measure, 0, points.length - 1, simplified);
|
||||
simplified.push({
|
||||
point: points[points.length - 1]
|
||||
point: points[points.length - 1],
|
||||
});
|
||||
return simplified;
|
||||
}
|
||||
|
||||
function ramerDouglasPeuckerRecursive(points: TrackPoint[], epsilon: number, measure: (a: TrackPoint, b: TrackPoint, c: TrackPoint) => number, start: number, end: number, simplified: SimplifiedTrackPoint[]) {
|
||||
function ramerDouglasPeuckerRecursive(
|
||||
points: TrackPoint[],
|
||||
epsilon: number,
|
||||
measure: (a: TrackPoint, b: TrackPoint, c: TrackPoint) => number,
|
||||
start: number,
|
||||
end: number,
|
||||
simplified: SimplifiedTrackPoint[]
|
||||
) {
|
||||
let largest = {
|
||||
index: 0,
|
||||
distance: 0
|
||||
distance: 0,
|
||||
};
|
||||
|
||||
for (let i = start + 1; i < end; i++) {
|
||||
@@ -45,111 +58,105 @@ function ramerDouglasPeuckerRecursive(points: TrackPoint[], epsilon: number, mea
|
||||
}
|
||||
}
|
||||
|
||||
export function crossarcDistance(point1: TrackPoint, point2: TrackPoint, point3: TrackPoint | Coordinates): number {
|
||||
return crossarc(point1.getCoordinates(), point2.getCoordinates(), point3 instanceof TrackPoint ? point3.getCoordinates() : point3);
|
||||
export function crossarcDistance(
|
||||
point1: TrackPoint | Coordinates,
|
||||
point2: TrackPoint | Coordinates,
|
||||
point3: TrackPoint | Coordinates
|
||||
): number {
|
||||
return crossarc(
|
||||
point1 instanceof TrackPoint ? point1.getCoordinates() : point1,
|
||||
point2 instanceof TrackPoint ? point2.getCoordinates() : point2,
|
||||
point3 instanceof TrackPoint ? point3.getCoordinates() : point3
|
||||
);
|
||||
}
|
||||
|
||||
const metersPerLatitudeDegree = 111320;
|
||||
|
||||
function getMetersPerLongitudeDegree(latitude: number): number {
|
||||
return Math.cos((latitude * Math.PI) / 180) * metersPerLatitudeDegree;
|
||||
}
|
||||
|
||||
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.
|
||||
// Calculates the perpendicular distance in meters
|
||||
// between a line segment (defined by p1 and p2) and a third point, p3.
|
||||
// Uses simple planar geometry (ignores earth curvature).
|
||||
|
||||
const rad = Math.PI / 180;
|
||||
const lat1 = coord1.lat * rad;
|
||||
const lat2 = coord2.lat * rad;
|
||||
const lat3 = coord3.lat * rad;
|
||||
// Convert to meters using approximate scaling
|
||||
const metersPerLongitudeDegree = getMetersPerLongitudeDegree(coord1.lat);
|
||||
|
||||
const lon1 = coord1.lon * rad;
|
||||
const lon2 = coord2.lon * rad;
|
||||
const lon3 = coord3.lon * rad;
|
||||
const x1 = coord1.lon * metersPerLongitudeDegree;
|
||||
const y1 = coord1.lat * metersPerLatitudeDegree;
|
||||
const x2 = coord2.lon * metersPerLongitudeDegree;
|
||||
const y2 = coord2.lat * metersPerLatitudeDegree;
|
||||
const x3 = coord3.lon * metersPerLongitudeDegree;
|
||||
const y3 = coord3.lat * metersPerLatitudeDegree;
|
||||
|
||||
// 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);
|
||||
const dx = x2 - x1;
|
||||
const dy = y2 - y1;
|
||||
const segmentLengthSquared = dx * dx + dy * dy;
|
||||
|
||||
let diff = Math.abs(bear13 - bear12);
|
||||
if (diff > Math.PI) {
|
||||
diff = 2 * Math.PI - diff;
|
||||
if (segmentLengthSquared === 0) {
|
||||
// p1 and p2 are the same point
|
||||
return Math.sqrt((x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1));
|
||||
}
|
||||
|
||||
// Is relative bearing obtuse?
|
||||
if (diff > (Math.PI / 2)) {
|
||||
return dis13;
|
||||
}
|
||||
// Project p3 onto the line defined by p1-p2
|
||||
const t = Math.max(0, Math.min(1, ((x3 - x1) * dx + (y3 - y1) * dy) / segmentLengthSquared));
|
||||
|
||||
// Find the cross-track distance.
|
||||
let dxt = Math.asin(Math.sin(dis13 / earthRadius) * Math.sin(bear13 - bear12)) * earthRadius;
|
||||
// Find the closest point on the segment
|
||||
const projX = x1 + t * dx;
|
||||
const projY = y1 + t * dy;
|
||||
|
||||
// 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);
|
||||
}
|
||||
// Return distance from p3 to the projected point
|
||||
return Math.sqrt((x3 - projX) * (x3 - projX) + (y3 - projY) * (y3 - projY));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
export function projectedPoint(point1: TrackPoint, point2: TrackPoint, point3: TrackPoint | Coordinates): Coordinates {
|
||||
return projected(point1.getCoordinates(), point2.getCoordinates(), point3 instanceof TrackPoint ? point3.getCoordinates() : point3);
|
||||
export function projectedPoint(
|
||||
point1: TrackPoint,
|
||||
point2: TrackPoint,
|
||||
point3: TrackPoint | Coordinates
|
||||
): Coordinates {
|
||||
return projected(
|
||||
point1.getCoordinates(),
|
||||
point2.getCoordinates(),
|
||||
point3 instanceof TrackPoint ? point3.getCoordinates() : point3
|
||||
);
|
||||
}
|
||||
|
||||
function projected(coord1: Coordinates, coord2: Coordinates, coord3: Coordinates): Coordinates {
|
||||
// Calculates the point on the line defined by p1 and p2
|
||||
// Calculates the point on the line segment defined by p1 and p2
|
||||
// that is closest to the third point, p3.
|
||||
// Input lat1,lon1,lat2,lon2,lat3,lon3 in degrees.
|
||||
// Uses simple planar geometry (ignores earth curvature).
|
||||
|
||||
const rad = Math.PI / 180;
|
||||
const lat1 = coord1.lat * rad;
|
||||
const lat2 = coord2.lat * rad;
|
||||
const lat3 = coord3.lat * rad;
|
||||
// Convert to meters using approximate scaling
|
||||
const metersPerLongitudeDegree = getMetersPerLongitudeDegree(coord1.lat);
|
||||
|
||||
const lon1 = coord1.lon * rad;
|
||||
const lon2 = coord2.lon * rad;
|
||||
const lon3 = coord3.lon * rad;
|
||||
const x1 = coord1.lon * metersPerLongitudeDegree;
|
||||
const y1 = coord1.lat * metersPerLatitudeDegree;
|
||||
const x2 = coord2.lon * metersPerLongitudeDegree;
|
||||
const y2 = coord2.lat * metersPerLatitudeDegree;
|
||||
const x3 = coord3.lon * metersPerLongitudeDegree;
|
||||
const y3 = coord3.lat * metersPerLatitudeDegree;
|
||||
|
||||
// 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);
|
||||
const dx = x2 - x1;
|
||||
const dy = y2 - y1;
|
||||
const segmentLengthSquared = dx * dx + dy * dy;
|
||||
|
||||
let diff = Math.abs(bear13 - bear12);
|
||||
if (diff > Math.PI) {
|
||||
diff = 2 * Math.PI - diff;
|
||||
}
|
||||
|
||||
// Is relative bearing obtuse?
|
||||
if (diff > (Math.PI / 2)) {
|
||||
if (segmentLengthSquared === 0) {
|
||||
// p1 and p2 are the same point
|
||||
return coord1;
|
||||
}
|
||||
|
||||
// Find the cross-track distance.
|
||||
let dxt = Math.asin(Math.sin(dis13 / earthRadius) * Math.sin(bear13 - bear12)) * earthRadius;
|
||||
// Project p3 onto the line defined by p1-p2
|
||||
const t = Math.max(0, Math.min(1, ((x3 - x1) * dx + (y3 - y1) * dy) / segmentLengthSquared));
|
||||
|
||||
// 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 coord2;
|
||||
} else {
|
||||
// Determine the closest point (p4) on the great circle
|
||||
const f = dis14 / earthRadius;
|
||||
const lat4 = Math.asin(Math.sin(lat1) * Math.cos(f) + Math.cos(lat1) * Math.sin(f) * Math.cos(bear12));
|
||||
const lon4 = lon1 + Math.atan2(Math.sin(bear12) * Math.sin(f) * Math.cos(lat1), Math.cos(f) - Math.sin(lat1) * Math.sin(lat4));
|
||||
// Find the closest point on the segment
|
||||
const projX = x1 + t * dx;
|
||||
const projY = y1 + t * dy;
|
||||
|
||||
return { lat: lat4 / rad, lon: lon4 / rad };
|
||||
}
|
||||
// Convert back to degrees
|
||||
return {
|
||||
lat: projY / metersPerLatitudeDegree,
|
||||
lon: projX / metersPerLongitudeDegree,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
import { TrackPoint } from './gpx';
|
||||
import { Coordinates } from './types';
|
||||
|
||||
export class GPXGlobalStatistics {
|
||||
length: number;
|
||||
distance: {
|
||||
moving: number;
|
||||
total: number;
|
||||
};
|
||||
time: {
|
||||
start: Date | undefined;
|
||||
end: Date | undefined;
|
||||
moving: number;
|
||||
total: number;
|
||||
};
|
||||
speed: {
|
||||
moving: number;
|
||||
total: number;
|
||||
};
|
||||
elevation: {
|
||||
gain: number;
|
||||
loss: number;
|
||||
};
|
||||
bounds: {
|
||||
southWest: Coordinates;
|
||||
northEast: Coordinates;
|
||||
};
|
||||
atemp: {
|
||||
avg: number;
|
||||
count: number;
|
||||
};
|
||||
hr: {
|
||||
avg: number;
|
||||
count: number;
|
||||
};
|
||||
cad: {
|
||||
avg: number;
|
||||
count: number;
|
||||
};
|
||||
power: {
|
||||
avg: number;
|
||||
count: number;
|
||||
};
|
||||
extensions: Record<string, Record<string, number>>;
|
||||
|
||||
constructor() {
|
||||
this.length = 0;
|
||||
this.distance = {
|
||||
moving: 0,
|
||||
total: 0,
|
||||
};
|
||||
this.time = {
|
||||
start: undefined,
|
||||
end: undefined,
|
||||
moving: 0,
|
||||
total: 0,
|
||||
};
|
||||
this.speed = {
|
||||
moving: 0,
|
||||
total: 0,
|
||||
};
|
||||
this.elevation = {
|
||||
gain: 0,
|
||||
loss: 0,
|
||||
};
|
||||
this.bounds = {
|
||||
southWest: {
|
||||
lat: 90,
|
||||
lon: 180,
|
||||
},
|
||||
northEast: {
|
||||
lat: -90,
|
||||
lon: -180,
|
||||
},
|
||||
};
|
||||
this.atemp = {
|
||||
avg: 0,
|
||||
count: 0,
|
||||
};
|
||||
this.hr = {
|
||||
avg: 0,
|
||||
count: 0,
|
||||
};
|
||||
this.cad = {
|
||||
avg: 0,
|
||||
count: 0,
|
||||
};
|
||||
this.power = {
|
||||
avg: 0,
|
||||
count: 0,
|
||||
};
|
||||
this.extensions = {};
|
||||
}
|
||||
|
||||
mergeWith(other: GPXGlobalStatistics): void {
|
||||
this.length += other.length;
|
||||
|
||||
this.distance.total += other.distance.total;
|
||||
this.distance.moving += other.distance.moving;
|
||||
|
||||
this.time.start =
|
||||
this.time.start !== undefined && other.time.start !== undefined
|
||||
? new Date(Math.min(this.time.start.getTime(), other.time.start.getTime()))
|
||||
: (this.time.start ?? other.time.start);
|
||||
this.time.end =
|
||||
this.time.end !== undefined && other.time.end !== undefined
|
||||
? new Date(Math.max(this.time.end.getTime(), other.time.end.getTime()))
|
||||
: (this.time.end ?? other.time.end);
|
||||
|
||||
this.time.total += other.time.total;
|
||||
this.time.moving += other.time.moving;
|
||||
|
||||
this.speed.moving =
|
||||
this.time.moving > 0 ? this.distance.moving / (this.time.moving / 3600) : 0;
|
||||
this.speed.total = this.time.total > 0 ? this.distance.total / (this.time.total / 3600) : 0;
|
||||
|
||||
this.elevation.gain += other.elevation.gain;
|
||||
this.elevation.loss += other.elevation.loss;
|
||||
|
||||
this.bounds.southWest.lat = Math.min(this.bounds.southWest.lat, other.bounds.southWest.lat);
|
||||
this.bounds.southWest.lon = Math.min(this.bounds.southWest.lon, other.bounds.southWest.lon);
|
||||
this.bounds.northEast.lat = Math.max(this.bounds.northEast.lat, other.bounds.northEast.lat);
|
||||
this.bounds.northEast.lon = Math.max(this.bounds.northEast.lon, other.bounds.northEast.lon);
|
||||
|
||||
this.atemp.avg =
|
||||
(this.atemp.count * this.atemp.avg + other.atemp.count * other.atemp.avg) /
|
||||
Math.max(1, this.atemp.count + other.atemp.count);
|
||||
this.atemp.count += other.atemp.count;
|
||||
this.hr.avg =
|
||||
(this.hr.count * this.hr.avg + other.hr.count * other.hr.avg) /
|
||||
Math.max(1, this.hr.count + other.hr.count);
|
||||
this.hr.count += other.hr.count;
|
||||
this.cad.avg =
|
||||
(this.cad.count * this.cad.avg + other.cad.count * other.cad.avg) /
|
||||
Math.max(1, this.cad.count + other.cad.count);
|
||||
this.cad.count += other.cad.count;
|
||||
this.power.avg =
|
||||
(this.power.count * this.power.avg + other.power.count * other.power.avg) /
|
||||
Math.max(1, this.power.count + other.power.count);
|
||||
this.power.count += other.power.count;
|
||||
|
||||
Object.keys(other.extensions).forEach((extension) => {
|
||||
if (this.extensions[extension] === undefined) {
|
||||
this.extensions[extension] = {};
|
||||
}
|
||||
Object.keys(other.extensions[extension]).forEach((value) => {
|
||||
if (this.extensions[extension][value] === undefined) {
|
||||
this.extensions[extension][value] = 0;
|
||||
}
|
||||
this.extensions[extension][value] += other.extensions[extension][value];
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class TrackPointLocalStatistics {
|
||||
distance: {
|
||||
moving: number;
|
||||
total: number;
|
||||
};
|
||||
time: {
|
||||
moving: number;
|
||||
total: number;
|
||||
};
|
||||
speed: number;
|
||||
elevation: {
|
||||
gain: number;
|
||||
loss: number;
|
||||
};
|
||||
slope: {
|
||||
at: number;
|
||||
segment: number;
|
||||
length: number;
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this.distance = {
|
||||
moving: 0,
|
||||
total: 0,
|
||||
};
|
||||
this.time = {
|
||||
moving: 0,
|
||||
total: 0,
|
||||
};
|
||||
this.speed = 0;
|
||||
this.elevation = {
|
||||
gain: 0,
|
||||
loss: 0,
|
||||
};
|
||||
this.slope = {
|
||||
at: 0,
|
||||
segment: 0,
|
||||
length: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class GPXLocalStatistics {
|
||||
points: TrackPoint[];
|
||||
data: TrackPointLocalStatistics[];
|
||||
|
||||
constructor() {
|
||||
this.points = [];
|
||||
this.data = [];
|
||||
}
|
||||
}
|
||||
|
||||
export type TrackPointWithLocalStatistics = {
|
||||
trkpt: TrackPoint;
|
||||
} & TrackPointLocalStatistics;
|
||||
|
||||
export class GPXStatistics {
|
||||
global: GPXGlobalStatistics;
|
||||
local: GPXLocalStatistics;
|
||||
|
||||
constructor() {
|
||||
this.global = new GPXGlobalStatistics();
|
||||
this.local = new GPXLocalStatistics();
|
||||
}
|
||||
|
||||
sliced(start: number, end: number): GPXGlobalStatistics {
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
} else if (start >= this.global.length) {
|
||||
return new GPXGlobalStatistics();
|
||||
}
|
||||
|
||||
if (end < start) {
|
||||
return new GPXGlobalStatistics();
|
||||
} else if (end >= this.global.length) {
|
||||
end = this.global.length - 1;
|
||||
}
|
||||
|
||||
if (start === 0 && end === this.global.length - 1) {
|
||||
return this.global;
|
||||
}
|
||||
|
||||
let statistics = new GPXGlobalStatistics();
|
||||
|
||||
statistics.length = end - start + 1;
|
||||
|
||||
statistics.distance.total =
|
||||
this.local.data[end].distance.total - this.local.data[start].distance.total;
|
||||
statistics.distance.moving =
|
||||
this.local.data[end].distance.moving - this.local.data[start].distance.moving;
|
||||
|
||||
statistics.time.start = this.local.points[start].time;
|
||||
statistics.time.end = this.local.points[end].time;
|
||||
|
||||
statistics.time.total = this.local.data[end].time.total - this.local.data[start].time.total;
|
||||
statistics.time.moving =
|
||||
this.local.data[end].time.moving - this.local.data[start].time.moving;
|
||||
|
||||
statistics.speed.moving =
|
||||
statistics.time.moving > 0
|
||||
? statistics.distance.moving / (statistics.time.moving / 3600)
|
||||
: 0;
|
||||
statistics.speed.total =
|
||||
statistics.time.total > 0
|
||||
? statistics.distance.total / (statistics.time.total / 3600)
|
||||
: 0;
|
||||
|
||||
statistics.elevation.gain =
|
||||
this.local.data[end].elevation.gain - this.local.data[start].elevation.gain;
|
||||
statistics.elevation.loss =
|
||||
this.local.data[end].elevation.loss - this.local.data[start].elevation.loss;
|
||||
|
||||
statistics.bounds.southWest.lat = this.global.bounds.southWest.lat;
|
||||
statistics.bounds.southWest.lon = this.global.bounds.southWest.lon;
|
||||
statistics.bounds.northEast.lat = this.global.bounds.northEast.lat;
|
||||
statistics.bounds.northEast.lon = this.global.bounds.northEast.lon;
|
||||
|
||||
statistics.atemp = this.global.atemp;
|
||||
statistics.hr = this.global.hr;
|
||||
statistics.cad = this.global.cad;
|
||||
statistics.power = this.global.power;
|
||||
|
||||
return statistics;
|
||||
}
|
||||
}
|
||||
|
||||
export class GPXStatisticsGroup {
|
||||
private _statistics: GPXStatistics[];
|
||||
private _cumulative: GPXGlobalStatistics[];
|
||||
private _slice: [number, number] | null = null;
|
||||
global: GPXGlobalStatistics;
|
||||
|
||||
constructor() {
|
||||
this._statistics = [];
|
||||
this._cumulative = [new GPXGlobalStatistics()];
|
||||
this.global = new GPXGlobalStatistics();
|
||||
}
|
||||
|
||||
add(statistics: GPXStatistics | GPXStatisticsGroup): void {
|
||||
if (statistics instanceof GPXStatisticsGroup) {
|
||||
statistics._statistics.forEach((stats) => this._add(stats));
|
||||
} else {
|
||||
this._add(statistics);
|
||||
}
|
||||
}
|
||||
|
||||
_add(statistics: GPXStatistics): void {
|
||||
this._statistics.push(statistics);
|
||||
const cumulative = new GPXGlobalStatistics();
|
||||
cumulative.mergeWith(this._cumulative[this._cumulative.length - 1]);
|
||||
cumulative.mergeWith(statistics.global);
|
||||
this._cumulative.push(cumulative);
|
||||
this.global.mergeWith(statistics.global);
|
||||
}
|
||||
|
||||
sliced(start: number, end: number): GPXGlobalStatistics {
|
||||
let sliced = new GPXGlobalStatistics();
|
||||
for (let i = 0; i < this._statistics.length; i++) {
|
||||
const statistics = this._statistics[i];
|
||||
const cumulative = this._cumulative[i];
|
||||
if (start < cumulative.length + statistics.global.length && end >= cumulative.length) {
|
||||
const localStart = Math.max(0, start - cumulative.length);
|
||||
const localEnd = Math.min(statistics.global.length - 1, end - cumulative.length);
|
||||
sliced.mergeWith(statistics.sliced(localStart, localEnd));
|
||||
}
|
||||
}
|
||||
return sliced;
|
||||
}
|
||||
|
||||
getTrackPoint(index: number): TrackPointWithLocalStatistics | undefined {
|
||||
if (this._slice !== null) {
|
||||
index += this._slice[0];
|
||||
}
|
||||
for (let i = 0; i < this._statistics.length; i++) {
|
||||
const statistics = this._statistics[i];
|
||||
const cumulative = this._cumulative[i];
|
||||
if (index < cumulative.length + statistics.global.length) {
|
||||
return this._getTrackPoint(cumulative, statistics, index - cumulative.length);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
_getTrackPoint(
|
||||
cumulative: GPXGlobalStatistics,
|
||||
statistics: GPXStatistics,
|
||||
index: number
|
||||
): TrackPointWithLocalStatistics {
|
||||
const point = statistics.local.points[index];
|
||||
return {
|
||||
trkpt: point,
|
||||
distance: {
|
||||
moving: statistics.local.data[index].distance.moving + cumulative.distance.moving,
|
||||
total: statistics.local.data[index].distance.total + cumulative.distance.total,
|
||||
},
|
||||
time: {
|
||||
moving: statistics.local.data[index].time.moving + cumulative.time.moving,
|
||||
total: statistics.local.data[index].time.total + cumulative.time.total,
|
||||
},
|
||||
speed: statistics.local.data[index].speed,
|
||||
elevation: {
|
||||
gain: statistics.local.data[index].elevation.gain + cumulative.elevation.gain,
|
||||
loss: statistics.local.data[index].elevation.loss + cumulative.elevation.loss,
|
||||
},
|
||||
slope: {
|
||||
at: statistics.local.data[index].slope.at,
|
||||
segment: statistics.local.data[index].slope.segment,
|
||||
length: statistics.local.data[index].slope.length,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
forEachTrackPoint(
|
||||
callback: (
|
||||
point: TrackPoint,
|
||||
distance: number,
|
||||
speed: number,
|
||||
slope: { at: number; segment: number; length: number },
|
||||
index: number
|
||||
) => void
|
||||
): void {
|
||||
for (let i = 0; i < this._statistics.length; i++) {
|
||||
const statistics = this._statistics[i];
|
||||
const cumulative = this._cumulative[i];
|
||||
statistics.local.points.forEach((point, index) =>
|
||||
callback(
|
||||
point,
|
||||
cumulative.distance.total + statistics.local.data[index].distance.total,
|
||||
statistics.local.data[index].speed,
|
||||
statistics.local.data[index].slope,
|
||||
cumulative.length + index
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,9 +67,9 @@ export type TrackExtensions = {
|
||||
};
|
||||
|
||||
export type LineStyleExtension = {
|
||||
color?: string;
|
||||
opacity?: number;
|
||||
weight?: number;
|
||||
'gpx_style:color'?: string;
|
||||
'gpx_style:opacity'?: number;
|
||||
'gpx_style:width'?: number;
|
||||
};
|
||||
|
||||
export type TrackSegmentType = {
|
||||
@@ -93,11 +93,11 @@ export type TrackPointExtension = {
|
||||
'gpxtpx:hr'?: number;
|
||||
'gpxtpx:cad'?: number;
|
||||
'gpxtpx:Extensions'?: Record<string, string>;
|
||||
}
|
||||
};
|
||||
|
||||
export type PowerExtension = {
|
||||
'gpxpx:PowerInWatts'?: number;
|
||||
}
|
||||
};
|
||||
|
||||
export type Author = {
|
||||
name?: string;
|
||||
@@ -114,12 +114,12 @@ export type RouteType = {
|
||||
type?: string;
|
||||
extensions?: TrackExtensions;
|
||||
rtept: WaypointType[];
|
||||
}
|
||||
};
|
||||
|
||||
export type RoutePointExtension = {
|
||||
'gpxx:rpt'?: GPXXRoutePoint[];
|
||||
}
|
||||
};
|
||||
|
||||
export type GPXXRoutePoint = {
|
||||
attributes: Coordinates;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
<type>Cycling</type>
|
||||
<extensions>
|
||||
<gpx_style:line>
|
||||
<color>#2d3ee9</color>
|
||||
<opacity>0.5</opacity>
|
||||
<weight>6</weight>
|
||||
<gpx_style:color>2d3ee9</gpx_style:color>
|
||||
<gpx_style:opacity>0.5</gpx_style:opacity>
|
||||
<gpx_style:width>6</gpx_style:width>
|
||||
</gpx_style:line>
|
||||
</extensions>
|
||||
<trkseg>
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"target": "ES2015",
|
||||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"moduleResolution": "node",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"include": ["src"]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
PUBLIC_MAPBOX_TOKEN=YOUR_MAPBOX_TOKEN
|
||||
PUBLIC_MAPTILER_KEY=YOUR_MAPTILER_KEY
|
||||
@@ -5,27 +5,27 @@ module.exports = {
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:svelte/recommended',
|
||||
'prettier'
|
||||
'prettier',
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint'],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020,
|
||||
extraFileExtensions: ['.svelte']
|
||||
extraFileExtensions: ['.svelte'],
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2017: true,
|
||||
node: true
|
||||
node: true,
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.svelte'],
|
||||
parser: 'svelte-eslint-parser',
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser'
|
||||
}
|
||||
}
|
||||
]
|
||||
parser: '@typescript-eslint/parser',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -8,3 +8,5 @@ node_modules
|
||||
!.env.example
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
static/*.webmanifest
|
||||
!static/en.manifest.webmanifest
|
||||
@@ -1,4 +0,0 @@
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
||||
@@ -1,14 +1,20 @@
|
||||
{
|
||||
"$schema": "https://shadcn-svelte.com/schema.json",
|
||||
"style": "default",
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.js",
|
||||
"css": "src/app.css",
|
||||
"baseColor": "slate"
|
||||
"baseColor": "neutral"
|
||||
},
|
||||
"aliases": {
|
||||
"components": "$lib/components",
|
||||
"utils": "$lib/utils"
|
||||
"utils": "$lib/utils",
|
||||
"ui": "$lib/components/ui",
|
||||
"hooks": "$lib/hooks",
|
||||
"lib": "$lib"
|
||||
},
|
||||
"typescript": true
|
||||
"typescript": true,
|
||||
"registry": "https://shadcn-svelte.com/registry",
|
||||
"style": "nova",
|
||||
"iconLibrary": "lucide",
|
||||
"menuColor": "default",
|
||||
"menuAccent": "subtle"
|
||||
}
|
||||
@@ -5,75 +5,80 @@
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"postbuild": "npx tsx src/lib/sitemap.ts",
|
||||
"prebuild": "npx tsx src/lib/scripts/pwa-manifest.ts",
|
||||
"postbuild": "npx tsx src/lib/scripts/sitemap.ts",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"format": "prettier --write ."
|
||||
"lint": "prettier --check . --config ../.prettierrc --ignore-path ../.prettierignore --ignore-path ./.gitignore && eslint .",
|
||||
"format": "prettier --write . --config ../.prettierrc --ignore-path ../.prettierignore --ignore-path ./.gitignore"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^3.2.5",
|
||||
"@sveltejs/adapter-static": "^3.0.5",
|
||||
"@sveltejs/enhanced-img": "^0.3.8",
|
||||
"@sveltejs/kit": "^2.6.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.2",
|
||||
"@types/eslint": "^8.56.12",
|
||||
"@fontsource-variable/inter": "^5.2.8",
|
||||
"@internationalized/date": "^3.12.0",
|
||||
"@lucide/svelte": "^1.7.0",
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
"@sveltejs/enhanced-img": "^0.6.0",
|
||||
"@sveltejs/kit": "^2.21.2",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.1.0",
|
||||
"@tailwindcss/vite": "^4.1.8",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@types/events": "^3.0.3",
|
||||
"@types/mapbox__mapbox-gl-geocoder": "^5.0.0",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/mapbox__sphericalmercator": "^1.2.3",
|
||||
"@types/mapbox__tilebelt": "^1.0.4",
|
||||
"@types/mapbox-gl": "^3.4.0",
|
||||
"@types/node": "^20.16.10",
|
||||
"@types/png.js": "^0.2.3",
|
||||
"@types/sanitize-html": "^2.13.0",
|
||||
"@types/node": "^22.15.30",
|
||||
"@types/sanitize-html": "^2.16.0",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||
"@typescript-eslint/parser": "^7.18.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.44.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.33.1",
|
||||
"@typescript-eslint/parser": "^8.33.1",
|
||||
"bits-ui": "^2.17.2",
|
||||
"clsx": "^2.1.1",
|
||||
"eslint": "^9.28.0",
|
||||
"eslint-config-prettier": "^10.1.5",
|
||||
"eslint-plugin-svelte": "^3.9.1",
|
||||
"events": "^3.3.0",
|
||||
"glob": "^10.4.5",
|
||||
"mdsvex": "^0.11.2",
|
||||
"glob": "^11.0.2",
|
||||
"lucide-static": "^0.513.0",
|
||||
"mdsvex": "^0.12.6",
|
||||
"mode-watcher": "^1.1.0",
|
||||
"paneforge": "^1.0.0-next.5",
|
||||
"postcss": "^8.4.47",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.7",
|
||||
"svelte": "^4.2.19",
|
||||
"svelte-check": "^3.8.6",
|
||||
"tailwindcss": "^3.4.13",
|
||||
"tslib": "^2.7.0",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"shadcn-svelte": "^1.2.7",
|
||||
"svelte": "^5.33.18",
|
||||
"svelte-check": "^4.0.0",
|
||||
"svelte-dnd-action": "^0.9.65",
|
||||
"svelte-sonner": "^1.1.0",
|
||||
"tailwind-merge": "^3.5.0",
|
||||
"tailwind-variants": "^3.2.2",
|
||||
"tailwindcss": "^4.1.8",
|
||||
"tslib": "^2.8.1",
|
||||
"tsx": "^4.19.1",
|
||||
"typescript": "^5.6.2",
|
||||
"vite": "^5.4.8",
|
||||
"vite-plugin-node-polyfills": "^0.22.0"
|
||||
"tw-animate-css": "^1.4.0",
|
||||
"typescript": "^5.8.3",
|
||||
"vaul-svelte": "^1.0.0-next.7",
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-wasm": "^3.6.0"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@docsearch/js": "^3.6.2",
|
||||
"@internationalized/date": "^3.5.5",
|
||||
"@mapbox/mapbox-gl-geocoder": "^5.0.3",
|
||||
"@mapbox/sphericalmercator": "^1.2.0",
|
||||
"@mapbox/tilebelt": "^1.0.2",
|
||||
"@types/mapbox__sphericalmercator": "^1.2.3",
|
||||
"bits-ui": "^0.21.15",
|
||||
"chart.js": "^4.4.4",
|
||||
"chartjs-plugin-zoom": "^2.0.1",
|
||||
"clsx": "^2.1.1",
|
||||
"dexie": "^4.0.8",
|
||||
"@docsearch/js": "^3.9.0",
|
||||
"@mapbox/sphericalmercator": "^2.0.1",
|
||||
"@mapbox/tilebelt": "^2.0.2",
|
||||
"@maplibre/maplibre-gl-geocoder": "^1.9.4",
|
||||
"chart.js": "^4.5.1",
|
||||
"chartjs-plugin-zoom": "^2.2.0",
|
||||
"dexie": "^4.0.11",
|
||||
"file-saver": "^2.0.5",
|
||||
"gpx": "file:../gpx",
|
||||
"gpx-rs": "file:../gpx-rs/pkg",
|
||||
"immer": "^10.1.1",
|
||||
"lucide-static": "^0.427.0",
|
||||
"lucide-svelte": "^0.427.0",
|
||||
"mapbox-gl": "^3.7.0",
|
||||
"jszip": "^3.10.1",
|
||||
"mapillary-js": "^4.1.2",
|
||||
"mode-watcher": "^0.3.1",
|
||||
"png.js": "^0.2.1",
|
||||
"sanitize-html": "^2.13.0",
|
||||
"sortablejs": "^1.15.3",
|
||||
"svelte-i18n": "^4.0.0",
|
||||
"svelte-sonner": "^0.3.28",
|
||||
"tailwind-merge": "^2.5.2",
|
||||
"tailwind-variants": "^0.2.1"
|
||||
"maplibre-gl": "^5.21.1",
|
||||
"sanitize-html": "^2.17.0",
|
||||
"sortablejs": "^1.15.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
@import 'tailwindcss';
|
||||
@import 'tw-animate-css';
|
||||
@import "shadcn-svelte/tailwind.css";
|
||||
@import "@fontsource-variable/inter";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
:root {
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--primary: oklch(0.205 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--destructive-foreground: hsl(0 0% 98%);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
|
||||
--support: rgb(220 15 130);
|
||||
--link: rgb(0 110 180);
|
||||
--selection: hsl(240 4.8% 93%);
|
||||
|
||||
--radius: 0.5rem;
|
||||
|
||||
--chart-1: oklch(0.87 0 0);
|
||||
|
||||
--chart-2: oklch(0.556 0 0);
|
||||
|
||||
--chart-3: oklch(0.439 0 0);
|
||||
|
||||
--chart-4: oklch(0.371 0 0);
|
||||
|
||||
--chart-5: oklch(0.269 0 0);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--destructive-foreground: hsl(0 0% 98%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
|
||||
--support: rgb(255 110 190);
|
||||
--link: rgb(80 190 255);
|
||||
--selection: hsl(240 3.7% 22%);
|
||||
--chart-1: oklch(0.87 0 0);
|
||||
--chart-2: oklch(0.556 0 0);
|
||||
--chart-3: oklch(0.439 0 0);
|
||||
--chart-4: oklch(0.371 0 0);
|
||||
--chart-5: oklch(0.269 0 0);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
/* Radius (for rounded-*) */
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
|
||||
/* Colors */
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-destructive-foreground: var(--destructive-foreground);
|
||||
--color-ring: var(--ring);
|
||||
--color-radius: var(--radius);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--color-support: var(--support);
|
||||
--color-link: var(--link);
|
||||
|
||||
--breakpoint-xs: 540px;
|
||||
|
||||
--font-sans: 'Inter Variable', sans-serif;
|
||||
|
||||
--color-chart-5: var(--chart-5);
|
||||
|
||||
--color-chart-4: var(--chart-4);
|
||||
|
||||
--color-chart-3: var(--chart-3);
|
||||
|
||||
--color-chart-2: var(--chart-2);
|
||||
|
||||
--color-chart-1: var(--chart-1);
|
||||
|
||||
--radius-2xl: calc(var(--radius) * 1.8);
|
||||
|
||||
--radius-3xl: calc(var(--radius) * 2.2);
|
||||
|
||||
--radius-4xl: calc(var(--radius) * 2.6);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
html {
|
||||
@apply font-sans;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="apple-touch-icon" href="%sveltekit.assets%/apple-touch-icon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
</head>
|
||||
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,86 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 45%;
|
||||
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--accent: 210 40% 92%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--destructive: 0 72.2% 50.6%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
|
||||
--support: 220 15 130;
|
||||
|
||||
--link: 0 110 180;
|
||||
|
||||
--ring: 222.2 84% 4.9%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
|
||||
--muted: 217.2 32.6% 17.5%;
|
||||
--muted-foreground: 215 20.2% 65.1%;
|
||||
|
||||
--popover: 222.2 84% 4.9%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
|
||||
--card: 222.2 84% 4.9%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
|
||||
--border: 217.2 32.6% 17.5%;
|
||||
--input: 217.2 32.6% 17.5%;
|
||||
|
||||
--primary: 210 40% 98%;
|
||||
--primary-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--secondary: 217.2 32.6% 17.5%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
|
||||
--accent: 217.2 32.6% 30%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
|
||||
--support: 255 110 190;
|
||||
|
||||
--link: 80 190 255;
|
||||
|
||||
--ring: hsl(212.7,26.8%,83.9);
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,14 @@ export async function handle({ event, resolve }) {
|
||||
|
||||
let headTag = `<head>
|
||||
<title>gpx.studio — ${title}</title>
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebSite",
|
||||
"name": "gpx.studio",
|
||||
"url": "https://gpx.studio"
|
||||
}
|
||||
</script>
|
||||
<meta name="description" content="${description}" />
|
||||
<meta property="og:title" content="gpx.studio — ${title}" />
|
||||
<meta property="og:description" content="${description}" />
|
||||
@@ -38,15 +46,19 @@ export async function handle({ event, resolve }) {
|
||||
<meta name="twitter:url" content="https://gpx.studio/" />
|
||||
<meta name="twitter:site" content="@gpxstudio" />
|
||||
<meta name="twitter:creator" content="@gpxstudio" />
|
||||
<link rel="alternate" hreflang="x-default" href="https://gpx.studio${getURLForLanguage('en', path)}" />`;
|
||||
<link rel="alternate" hreflang="x-default" href="https://gpx.studio${getURLForLanguage('en', path)}" />
|
||||
<link rel="manifest" href="/${language}.manifest.webmanifest" />`;
|
||||
|
||||
if (page !== '404') {
|
||||
for (let lang of Object.keys(languages)) {
|
||||
headTag += ` <link rel="alternate" hreflang="${lang}" href="https://gpx.studio${getURLForLanguage(lang, path)}" />
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
const response = await resolve(event, {
|
||||
transformPageChunk: ({ html }) => html.replace('<html>', htmlTag).replace('<head>', headTag),
|
||||
transformPageChunk: ({ html }) =>
|
||||
html.replace('<html>', htmlTag).replace('<head>', headTag),
|
||||
});
|
||||
|
||||
return response;
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
export const surfaceColors: { [key: string]: string } = {
|
||||
"missing": "#d1d1d1",
|
||||
"paved": "#8c8c8c",
|
||||
"unpaved": "#6b443a",
|
||||
"asphalt": "#8c8c8c",
|
||||
"concrete": "#8c8c8c",
|
||||
"cobblestone": "#ffd991",
|
||||
"paving_stones": "#8c8c8c",
|
||||
"sett": "#ffd991",
|
||||
"metal": "#8c8c8c",
|
||||
"wood": "#6b443a",
|
||||
"compacted": "#ffffa8",
|
||||
"fine_gravel": "#ffffa8",
|
||||
"gravel": "#ffffa8",
|
||||
"pebblestone": "#ffffa8",
|
||||
"rock": "#ffd991",
|
||||
"dirt": "#ffffa8",
|
||||
"ground": "#6b443a",
|
||||
"earth": "#6b443a",
|
||||
"mud": "#6b443a",
|
||||
"sand": "#ffffc4",
|
||||
"grass": "#61b55c",
|
||||
"grass_paver": "#61b55c",
|
||||
"clay": "#6b443a",
|
||||
"stone": "#ffd991",
|
||||
missing: '#d1d1d1',
|
||||
paved: '#8c8c8c',
|
||||
unpaved: '#6b443a',
|
||||
asphalt: '#8c8c8c',
|
||||
concrete: '#8c8c8c',
|
||||
cobblestone: '#ffd991',
|
||||
paving_stones: '#8c8c8c',
|
||||
sett: '#ffd991',
|
||||
metal: '#8c8c8c',
|
||||
wood: '#6b443a',
|
||||
compacted: '#ffffa8',
|
||||
fine_gravel: '#ffffa8',
|
||||
gravel: '#ffffa8',
|
||||
pebblestone: '#ffffa8',
|
||||
rock: '#ffd991',
|
||||
dirt: '#ffffa8',
|
||||
ground: '#6b443a',
|
||||
earth: '#6b443a',
|
||||
mud: '#6b443a',
|
||||
sand: '#ffffc4',
|
||||
grass: '#61b55c',
|
||||
grass_paver: '#61b55c',
|
||||
clay: '#6b443a',
|
||||
stone: '#ffd991',
|
||||
};
|
||||
|
||||
export function getSurfaceColor(surface: string): string {
|
||||
@@ -30,66 +30,72 @@ export function getSurfaceColor(surface: string): string {
|
||||
}
|
||||
|
||||
export const highwayColors: { [key: string]: string } = {
|
||||
"missing": "#d1d1d1",
|
||||
"motorway": "#ff4d33",
|
||||
"motorway_link": "#ff4d33",
|
||||
"trunk": "#ff5e4d",
|
||||
"trunk_link": "#ff947f",
|
||||
"primary": "#ff6e5c",
|
||||
"primary_link": "#ff6e5c",
|
||||
"secondary": "#ff8d7b",
|
||||
"secondary_link": "#ff8d7b",
|
||||
"tertiary": "#ffd75f",
|
||||
"tertiary_link": "#ffd75f",
|
||||
"unclassified": "#f1f2a5",
|
||||
"road": "#f1f2a5",
|
||||
"residential": "#73b2ff",
|
||||
"living_street": "#73b2ff",
|
||||
"service": "#9c9cd9",
|
||||
"track": "#a8e381",
|
||||
"footway": "#a8e381",
|
||||
"path": "#a8e381",
|
||||
"pedestrian": "#a8e381",
|
||||
"cycleway": "#9de2ff",
|
||||
"construction": "#e09a4a",
|
||||
"bridleway": "#946f43",
|
||||
"raceway": "#ff0000",
|
||||
"rest_area": "#9c9cd9",
|
||||
"services": "#9c9cd9",
|
||||
"corridor": "#474747",
|
||||
"elevator": "#474747",
|
||||
"steps": "#474747",
|
||||
"bus_stop": "#8545a3",
|
||||
"busway": "#8545a3",
|
||||
"via_ferrata": "#474747"
|
||||
missing: '#d1d1d1',
|
||||
motorway: '#ff4d33',
|
||||
motorway_link: '#ff4d33',
|
||||
trunk: '#ff5e4d',
|
||||
trunk_link: '#ff947f',
|
||||
primary: '#ff6e5c',
|
||||
primary_link: '#ff6e5c',
|
||||
secondary: '#ff8d7b',
|
||||
secondary_link: '#ff8d7b',
|
||||
tertiary: '#ffd75f',
|
||||
tertiary_link: '#ffd75f',
|
||||
unclassified: '#f1f2a5',
|
||||
road: '#f1f2a5',
|
||||
residential: '#73b2ff',
|
||||
living_street: '#73b2ff',
|
||||
service: '#9c9cd9',
|
||||
track: '#a8e381',
|
||||
footway: '#a8e381',
|
||||
path: '#a8e381',
|
||||
pedestrian: '#a8e381',
|
||||
cycleway: '#9de2ff',
|
||||
construction: '#e09a4a',
|
||||
bridleway: '#946f43',
|
||||
raceway: '#ff0000',
|
||||
rest_area: '#9c9cd9',
|
||||
services: '#9c9cd9',
|
||||
corridor: '#474747',
|
||||
elevator: '#474747',
|
||||
steps: '#474747',
|
||||
bus_stop: '#8545a3',
|
||||
busway: '#8545a3',
|
||||
via_ferrata: '#474747',
|
||||
};
|
||||
|
||||
export const sacScaleColors: { [key: string]: string } = {
|
||||
"hiking": "#007700",
|
||||
"mountain_hiking": "#1843ad",
|
||||
"demanding_mountain_hiking": "#ffff00",
|
||||
"alpine_hiking": "#ff9233",
|
||||
"demanding_alpine_hiking": "#ff0000",
|
||||
"difficult_alpine_hiking": "#000000",
|
||||
hiking: '#007700',
|
||||
mountain_hiking: '#1843ad',
|
||||
demanding_mountain_hiking: '#ffff00',
|
||||
alpine_hiking: '#ff9233',
|
||||
demanding_alpine_hiking: '#ff0000',
|
||||
difficult_alpine_hiking: '#000000',
|
||||
};
|
||||
|
||||
export const mtbScaleColors: { [key: string]: string } = {
|
||||
"0-": "#007700",
|
||||
"0": "#007700",
|
||||
"0+": "#007700",
|
||||
"1-": "#1843ad",
|
||||
"1": "#1843ad",
|
||||
"1+": "#1843ad",
|
||||
"2-": "#ffff00",
|
||||
"2": "#ffff00",
|
||||
"2+": "#ffff00",
|
||||
"3": "#ff0000",
|
||||
"4": "#00ff00",
|
||||
"5": "#000000",
|
||||
"6": "#b105eb",
|
||||
'0-': '#007700',
|
||||
'0': '#007700',
|
||||
'0+': '#007700',
|
||||
'1-': '#1843ad',
|
||||
'1': '#1843ad',
|
||||
'1+': '#1843ad',
|
||||
'2-': '#ffff00',
|
||||
'2': '#ffff00',
|
||||
'2+': '#ffff00',
|
||||
'3': '#ff0000',
|
||||
'4': '#00ff00',
|
||||
'5': '#000000',
|
||||
'6': '#b105eb',
|
||||
};
|
||||
|
||||
function createPattern(backgroundColor: string, sacScaleColor: string | undefined, mtbScaleColor: string | undefined, size: number = 16, lineWidth: number = 4) {
|
||||
function createPattern(
|
||||
backgroundColor: string,
|
||||
sacScaleColor: string | undefined,
|
||||
mtbScaleColor: string | undefined,
|
||||
size: number = 16,
|
||||
lineWidth: number = 4
|
||||
) {
|
||||
let canvas = document.createElement('canvas');
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
@@ -104,11 +110,11 @@ function createPattern(backgroundColor: string, sacScaleColor: string | undefine
|
||||
if (sacScaleColor) {
|
||||
ctx.strokeStyle = sacScaleColor;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(halfSize - halfLineWidth, - halfLineWidth);
|
||||
ctx.moveTo(halfSize - halfLineWidth, -halfLineWidth);
|
||||
ctx.lineTo(size + halfLineWidth, halfSize + halfLineWidth);
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(- halfLineWidth, halfSize - halfLineWidth);
|
||||
ctx.moveTo(-halfLineWidth, halfSize - halfLineWidth);
|
||||
ctx.lineTo(halfSize + halfLineWidth, size + halfLineWidth);
|
||||
ctx.stroke();
|
||||
}
|
||||
@@ -119,8 +125,8 @@ function createPattern(backgroundColor: string, sacScaleColor: string | undefine
|
||||
ctx.lineTo(size + halfLineWidth, halfSize - halfLineWidth);
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(- halfLineWidth, halfSize + halfLineWidth);
|
||||
ctx.lineTo(halfSize + halfLineWidth, - halfLineWidth);
|
||||
ctx.moveTo(-halfLineWidth, halfSize + halfLineWidth);
|
||||
ctx.lineTo(halfSize + halfLineWidth, -halfLineWidth);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
@@ -128,12 +134,16 @@ function createPattern(backgroundColor: string, sacScaleColor: string | undefine
|
||||
}
|
||||
|
||||
const patterns: Record<string, string | CanvasPattern> = {};
|
||||
export function getHighwayColor(highway: string, sacScale: string | undefined, mtbScale: string | undefined) {
|
||||
export function getHighwayColor(
|
||||
highway: string,
|
||||
sacScale: string | undefined,
|
||||
mtbScale: string | undefined
|
||||
) {
|
||||
let backgroundColor = highwayColors[highway] ? highwayColors[highway] : highwayColors.missing;
|
||||
let sacScaleColor = sacScale ? sacScaleColors[sacScale] : undefined;
|
||||
let mtbScaleColor = mtbScale ? mtbScaleColors[mtbScale] : undefined;
|
||||
if (sacScale || mtbScale) {
|
||||
let patternId = `${backgroundColor}-${[sacScale, mtbScale].filter(x => x).join('-')}`;
|
||||
let patternId = `${backgroundColor}-${[sacScale, mtbScale].filter((x) => x).join('-')}`;
|
||||
if (!patterns[patternId]) {
|
||||
patterns[patternId] = createPattern(backgroundColor, sacScaleColor, mtbScaleColor);
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 313 KiB |
|
After Width: | Height: | Size: 729 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
Before Width: | Height: | Size: 768 KiB After Width: | Height: | Size: 525 KiB |
|
Before Width: | Height: | Size: 596 KiB After Width: | Height: | Size: 710 KiB |
|
Before Width: | Height: | Size: 4.3 MiB |
|
Before Width: | Height: | Size: 5.4 MiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
Before Width: | Height: | Size: 2.9 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 3.6 MiB |
|
Before Width: | Height: | Size: 6.9 MiB |
|
Before Width: | Height: | Size: 448 KiB |
@@ -1,10 +1,73 @@
|
||||
import { Landmark, Icon, Shell, Bike, Building, Tent, Car, Wrench, ShoppingBasket, Droplet, DoorOpen, Trees, Fuel, Home, Info, TreeDeciduous, CircleParking, Cross, Utensils, Construction, BrickWall, ShowerHead, Mountain, Phone, TrainFront, Bed, Binoculars, TriangleAlert, Anchor } from "lucide-svelte";
|
||||
import { Landmark as LandmarkSvg, Shell as ShellSvg, Bike as BikeSvg, Building as BuildingSvg, Tent as TentSvg, Car as CarSvg, Wrench as WrenchSvg, ShoppingBasket as ShoppingBasketSvg, Droplet as DropletSvg, DoorOpen as DoorOpenSvg, Trees as TreesSvg, Fuel as FuelSvg, Home as HomeSvg, Info as InfoSvg, TreeDeciduous as TreeDeciduousSvg, CircleParking as CircleParkingSvg, Cross as CrossSvg, Utensils as UtensilsSvg, Construction as ConstructionSvg, BrickWall as BrickWallSvg, ShowerHead as ShowerHeadSvg, Mountain as MountainSvg, Phone as PhoneSvg, TrainFront as TrainFrontSvg, Bed as BedSvg, Binoculars as BinocularsSvg, TriangleAlert as TriangleAlertSvg, Anchor as AnchorSvg } from "lucide-static";
|
||||
import type { ComponentType } from "svelte";
|
||||
import {
|
||||
Landmark,
|
||||
Shell,
|
||||
Bike,
|
||||
Building,
|
||||
Tent,
|
||||
Car,
|
||||
Wrench,
|
||||
ShoppingBasket,
|
||||
Droplet,
|
||||
DoorOpen,
|
||||
Trees,
|
||||
Fuel,
|
||||
House,
|
||||
Info,
|
||||
TreeDeciduous,
|
||||
CircleParking,
|
||||
Cross,
|
||||
Utensils,
|
||||
Construction,
|
||||
BrickWall,
|
||||
ShowerHead,
|
||||
Mountain,
|
||||
Phone,
|
||||
TrainFront,
|
||||
Bed,
|
||||
Binoculars,
|
||||
TriangleAlert,
|
||||
Anchor,
|
||||
Toilet,
|
||||
X,
|
||||
type IconProps,
|
||||
} from '@lucide/svelte';
|
||||
import {
|
||||
Landmark as LandmarkSvg,
|
||||
Shell as ShellSvg,
|
||||
Bike as BikeSvg,
|
||||
Building as BuildingSvg,
|
||||
Tent as TentSvg,
|
||||
Car as CarSvg,
|
||||
Wrench as WrenchSvg,
|
||||
ShoppingBasket as ShoppingBasketSvg,
|
||||
Droplet as DropletSvg,
|
||||
DoorOpen as DoorOpenSvg,
|
||||
Trees as TreesSvg,
|
||||
Fuel as FuelSvg,
|
||||
House as HouseSvg,
|
||||
Info as InfoSvg,
|
||||
TreeDeciduous as TreeDeciduousSvg,
|
||||
CircleParking as CircleParkingSvg,
|
||||
Cross as CrossSvg,
|
||||
Utensils as UtensilsSvg,
|
||||
Construction as ConstructionSvg,
|
||||
BrickWall as BrickWallSvg,
|
||||
ShowerHead as ShowerHeadSvg,
|
||||
Mountain as MountainSvg,
|
||||
Phone as PhoneSvg,
|
||||
TrainFront as TrainFrontSvg,
|
||||
Bed as BedSvg,
|
||||
Binoculars as BinocularsSvg,
|
||||
TriangleAlert as TriangleAlertSvg,
|
||||
Anchor as AnchorSvg,
|
||||
Toilet as ToiletSvg,
|
||||
X as XSvg,
|
||||
} from 'lucide-static';
|
||||
import type { Component } from 'svelte';
|
||||
|
||||
export type Symbol = {
|
||||
value: string;
|
||||
icon?: ComponentType<Icon>;
|
||||
icon?: Component<IconProps>;
|
||||
iconSvg?: string;
|
||||
};
|
||||
|
||||
@@ -20,18 +83,34 @@ export const symbols: { [key: string]: Symbol } = {
|
||||
campground: { value: 'Campground', icon: Tent, iconSvg: TentSvg },
|
||||
car: { value: 'Car', icon: Car, iconSvg: CarSvg },
|
||||
car_repair: { value: 'Car Repair', icon: Wrench, iconSvg: WrenchSvg },
|
||||
convenience_store: { value: 'Convenience Store', icon: ShoppingBasket, iconSvg: ShoppingBasketSvg },
|
||||
crossing: { value: 'Crossing' },
|
||||
department_store: { value: 'Department Store', icon: ShoppingBasket, iconSvg: ShoppingBasketSvg },
|
||||
convenience_store: {
|
||||
value: 'Convenience Store',
|
||||
icon: ShoppingBasket,
|
||||
iconSvg: ShoppingBasketSvg,
|
||||
},
|
||||
crossing: {
|
||||
value: 'Crossing',
|
||||
icon: X,
|
||||
iconSvg: XSvg,
|
||||
},
|
||||
department_store: {
|
||||
value: 'Department Store',
|
||||
icon: ShoppingBasket,
|
||||
iconSvg: ShoppingBasketSvg,
|
||||
},
|
||||
drinking_water: { value: 'Drinking Water', icon: Droplet, iconSvg: DropletSvg },
|
||||
exit: { value: 'Exit', icon: DoorOpen, iconSvg: DoorOpenSvg },
|
||||
lodge: { value: 'Lodge', icon: Home, iconSvg: HomeSvg },
|
||||
lodge: { value: 'Lodge', icon: House, iconSvg: HouseSvg },
|
||||
lodging: { value: 'Lodging', icon: Bed, iconSvg: BedSvg },
|
||||
forest: { value: 'Forest', icon: Trees, iconSvg: TreesSvg },
|
||||
gas_station: { value: 'Gas Station', icon: Fuel, iconSvg: FuelSvg },
|
||||
ground_transportation: { value: 'Ground Transportation', icon: TrainFront, iconSvg: TrainFrontSvg },
|
||||
ground_transportation: {
|
||||
value: 'Ground Transportation',
|
||||
icon: TrainFront,
|
||||
iconSvg: TrainFrontSvg,
|
||||
},
|
||||
hotel: { value: 'Hotel', icon: Bed, iconSvg: BedSvg },
|
||||
house: { value: 'House', icon: Home, iconSvg: HomeSvg },
|
||||
house: { value: 'House', icon: House, iconSvg: HouseSvg },
|
||||
information: { value: 'Information', icon: Info, iconSvg: InfoSvg },
|
||||
park: { value: 'Park', icon: TreeDeciduous, iconSvg: TreeDeciduousSvg },
|
||||
parking_area: { value: 'Parking Area', icon: CircleParking, iconSvg: CircleParkingSvg },
|
||||
@@ -39,7 +118,7 @@ export const symbols: { [key: string]: Symbol } = {
|
||||
picnic_area: { value: 'Picnic Area', icon: Utensils, iconSvg: UtensilsSvg },
|
||||
restaurant: { value: 'Restaurant', icon: Utensils, iconSvg: UtensilsSvg },
|
||||
restricted_area: { value: 'Restricted Area', icon: Construction, iconSvg: ConstructionSvg },
|
||||
restroom: { value: 'Restroom' },
|
||||
restroom: { value: 'Restroom', icon: Toilet, iconSvg: ToiletSvg },
|
||||
road: { value: 'Road', icon: BrickWall, iconSvg: BrickWallSvg },
|
||||
scenic_area: { value: 'Scenic Area', icon: Binoculars, iconSvg: BinocularsSvg },
|
||||
shelter: { value: 'Shelter', icon: Tent, iconSvg: TentSvg },
|
||||
@@ -55,6 +134,6 @@ export function getSymbolKey(value: string | undefined): string | undefined {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
} else {
|
||||
return Object.keys(symbols).find(key => symbols[key].value === value);
|
||||
return Object.keys(symbols).find((key) => symbols[key].value === value);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,11 @@
|
||||
import docsearch from '@docsearch/js';
|
||||
import '@docsearch/css';
|
||||
import { onMount } from 'svelte';
|
||||
import { _, locale, waitLocale } from 'svelte-i18n';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
|
||||
let props: {
|
||||
class?: string;
|
||||
} = $props();
|
||||
|
||||
let mounted = false;
|
||||
|
||||
@@ -13,34 +17,34 @@
|
||||
indexName: 'gpx',
|
||||
container: '#docsearch',
|
||||
searchParameters: {
|
||||
facetFilters: ['lang:' + ($locale ?? 'en')]
|
||||
facetFilters: ['lang:' + i18n.lang],
|
||||
},
|
||||
placeholder: $_('docs.search.search'),
|
||||
placeholder: i18n._('docs.search.search'),
|
||||
disableUserPersonalization: true,
|
||||
translations: {
|
||||
button: {
|
||||
buttonText: $_('docs.search.search'),
|
||||
buttonAriaLabel: $_('docs.search.search')
|
||||
buttonText: i18n._('docs.search.search'),
|
||||
buttonAriaLabel: i18n._('docs.search.search'),
|
||||
},
|
||||
modal: {
|
||||
searchBox: {
|
||||
resetButtonTitle: $_('docs.search.clear'),
|
||||
resetButtonAriaLabel: $_('docs.search.clear'),
|
||||
cancelButtonText: $_('docs.search.cancel'),
|
||||
cancelButtonAriaLabel: $_('docs.search.cancel'),
|
||||
searchInputLabel: $_('docs.search.search')
|
||||
resetButtonTitle: i18n._('docs.search.clear'),
|
||||
resetButtonAriaLabel: i18n._('docs.search.clear'),
|
||||
cancelButtonText: i18n._('docs.search.cancel'),
|
||||
cancelButtonAriaLabel: i18n._('docs.search.cancel'),
|
||||
searchInputLabel: i18n._('docs.search.search'),
|
||||
},
|
||||
footer: {
|
||||
selectText: $_('docs.search.to_select'),
|
||||
navigateText: $_('docs.search.to_navigate'),
|
||||
closeText: $_('docs.search.to_close')
|
||||
selectText: i18n._('docs.search.to_select'),
|
||||
navigateText: i18n._('docs.search.to_navigate'),
|
||||
closeText: i18n._('docs.search.to_close'),
|
||||
},
|
||||
noResultsScreen: {
|
||||
noResultsText: $_('docs.search.no_results'),
|
||||
suggestedQueryText: $_('docs.search.no_results_suggestion')
|
||||
}
|
||||
}
|
||||
}
|
||||
noResultsText: i18n._('docs.search.no_results'),
|
||||
suggestedQueryText: i18n._('docs.search.no_results_suggestion'),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,13 +52,21 @@
|
||||
mounted = true;
|
||||
});
|
||||
|
||||
$: if (mounted && $locale) {
|
||||
waitLocale().then(initDocsearch);
|
||||
$effect(() => {
|
||||
if (mounted && i18n.lang && !i18n.isLoading) {
|
||||
initDocsearch();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<link rel="preconnect" href="https://21XLD94PE3-dsn.algolia.net" crossorigin />
|
||||
</svelte:head>
|
||||
|
||||
<div id="docsearch" {...$$restProps}></div>
|
||||
<div id="docsearch" class={props.class ?? ''}></div>
|
||||
|
||||
<style>
|
||||
#docsearch :global(button) {
|
||||
margin-left: 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,28 +1,38 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip/index.js';
|
||||
import type { Builder } from 'bits-ui';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
export let variant:
|
||||
| 'default'
|
||||
| 'secondary'
|
||||
| 'link'
|
||||
| 'destructive'
|
||||
| 'outline'
|
||||
| 'ghost'
|
||||
| undefined = 'default';
|
||||
export let label: string;
|
||||
export let side: 'top' | 'right' | 'bottom' | 'left' = 'top';
|
||||
export let builders: Builder[] = [];
|
||||
const {
|
||||
variant = 'default',
|
||||
label,
|
||||
side = 'top',
|
||||
disabled = false,
|
||||
class: className = '',
|
||||
children,
|
||||
onclick,
|
||||
}: {
|
||||
variant?: 'default' | 'secondary' | 'link' | 'destructive' | 'outline' | 'ghost';
|
||||
label: string;
|
||||
side?: 'top' | 'right' | 'bottom' | 'left';
|
||||
disabled?: boolean;
|
||||
class?: string;
|
||||
children: Snippet;
|
||||
onclick?: (event: MouseEvent) => void;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger asChild let:builder>
|
||||
<Button builders={[...builders, builder]} {variant} {...$$restProps} on:click>
|
||||
<slot />
|
||||
<Tooltip.Provider>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
{#snippet child({ props })}
|
||||
<Button {...props} {variant} class="bg-inherit {className}" {onclick}>
|
||||
{@render children()}
|
||||
</Button>
|
||||
{/snippet}
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content {side}>
|
||||
<span>{label}</span>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Provider>
|
||||
|
||||
@@ -1,671 +0,0 @@
|
||||
<script lang="ts">
|
||||
import ButtonWithTooltip from '$lib/components/ButtonWithTooltip.svelte';
|
||||
import * as Popover from '$lib/components/ui/popover';
|
||||
import * as ToggleGroup from '$lib/components/ui/toggle-group';
|
||||
import Chart from 'chart.js/auto';
|
||||
import mapboxgl from 'mapbox-gl';
|
||||
import { map } from '$lib/stores';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import {
|
||||
BrickWall,
|
||||
TriangleRight,
|
||||
HeartPulse,
|
||||
Orbit,
|
||||
SquareActivity,
|
||||
Thermometer,
|
||||
Zap,
|
||||
Circle,
|
||||
Check,
|
||||
ChartNoAxesColumn,
|
||||
Construction
|
||||
} from 'lucide-svelte';
|
||||
import { getSlopeColor, getSurfaceColor, getHighwayColor } from '$lib/assets/colors';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import {
|
||||
getCadenceWithUnits,
|
||||
getConvertedDistance,
|
||||
getConvertedElevation,
|
||||
getConvertedTemperature,
|
||||
getConvertedVelocity,
|
||||
getDistanceUnits,
|
||||
getDistanceWithUnits,
|
||||
getElevationWithUnits,
|
||||
getHeartRateWithUnits,
|
||||
getPowerWithUnits,
|
||||
getTemperatureWithUnits,
|
||||
getVelocityWithUnits
|
||||
} from '$lib/units';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import type { GPXStatistics } from 'gpx';
|
||||
import { settings } from '$lib/db';
|
||||
import { mode } from 'mode-watcher';
|
||||
import { df } from '$lib/utils';
|
||||
|
||||
export let gpxStatistics: Writable<GPXStatistics>;
|
||||
export let slicedGPXStatistics: Writable<[GPXStatistics, number, number] | undefined>;
|
||||
export let additionalDatasets: string[];
|
||||
export let elevationFill: 'slope' | 'surface' | 'highway' | undefined;
|
||||
export let showControls: boolean = true;
|
||||
|
||||
const { distanceUnits, velocityUnits, temperatureUnits } = settings;
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
let overlay: HTMLCanvasElement;
|
||||
let chart: Chart;
|
||||
|
||||
Chart.defaults.font.family =
|
||||
'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"'; // Tailwind CSS font
|
||||
|
||||
let marker: mapboxgl.Marker | null = null;
|
||||
let dragging = false;
|
||||
let panning = false;
|
||||
|
||||
let options = {
|
||||
animation: false,
|
||||
parsing: false,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
x: {
|
||||
type: 'linear',
|
||||
ticks: {
|
||||
callback: function (value: number) {
|
||||
return `${value.toFixed(1).replace(/\.0+$/, '')} ${getDistanceUnits()}`;
|
||||
},
|
||||
align: 'inner',
|
||||
maxRotation: 0
|
||||
}
|
||||
},
|
||||
y: {
|
||||
type: 'linear',
|
||||
ticks: {
|
||||
callback: function (value: number) {
|
||||
return getElevationWithUnits(value, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
datasets: {
|
||||
line: {
|
||||
pointRadius: 0,
|
||||
tension: 0.4,
|
||||
borderWidth: 2,
|
||||
cubicInterpolationMode: 'monotone'
|
||||
}
|
||||
},
|
||||
interaction: {
|
||||
mode: 'nearest',
|
||||
axis: 'x',
|
||||
intersect: false
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
decimation: {
|
||||
enabled: true
|
||||
},
|
||||
tooltip: {
|
||||
enabled: () => !dragging && !panning,
|
||||
callbacks: {
|
||||
title: function () {
|
||||
return '';
|
||||
},
|
||||
label: function (context: Chart.TooltipContext) {
|
||||
let point = context.raw;
|
||||
if (context.datasetIndex === 0) {
|
||||
if ($map && marker) {
|
||||
if (dragging) {
|
||||
marker.remove();
|
||||
} else {
|
||||
marker.setLngLat(point.coordinates);
|
||||
marker.addTo($map);
|
||||
}
|
||||
}
|
||||
return `${$_('quantities.elevation')}: ${getElevationWithUnits(point.y, false)}`;
|
||||
} else if (context.datasetIndex === 1) {
|
||||
return `${$velocityUnits === 'speed' ? $_('quantities.speed') : $_('quantities.pace')}: ${getVelocityWithUnits(point.y, false)}`;
|
||||
} else if (context.datasetIndex === 2) {
|
||||
return `${$_('quantities.heartrate')}: ${getHeartRateWithUnits(point.y)}`;
|
||||
} else if (context.datasetIndex === 3) {
|
||||
return `${$_('quantities.cadence')}: ${getCadenceWithUnits(point.y)}`;
|
||||
} else if (context.datasetIndex === 4) {
|
||||
return `${$_('quantities.temperature')}: ${getTemperatureWithUnits(point.y, false)}`;
|
||||
} else if (context.datasetIndex === 5) {
|
||||
return `${$_('quantities.power')}: ${getPowerWithUnits(point.y)}`;
|
||||
}
|
||||
},
|
||||
afterBody: function (contexts: Chart.TooltipContext[]) {
|
||||
let context = contexts.filter((context) => context.datasetIndex === 0);
|
||||
if (context.length === 0) return;
|
||||
let point = context[0].raw;
|
||||
let slope = {
|
||||
at: point.slope.at.toFixed(1),
|
||||
segment: point.slope.segment.toFixed(1),
|
||||
length: getDistanceWithUnits(point.slope.length)
|
||||
};
|
||||
let surface = point.extensions.surface ? point.extensions.surface : 'unknown';
|
||||
let highway = point.extensions.highway ? point.extensions.highway : 'unknown';
|
||||
let sacScale = point.extensions.sac_scale;
|
||||
let mtbScale = point.extensions.mtb_scale;
|
||||
|
||||
let labels = [
|
||||
` ${$_('quantities.distance')}: ${getDistanceWithUnits(point.x, false)}`,
|
||||
` ${$_('quantities.slope')}: ${slope.at} %${elevationFill === 'slope' ? ` (${slope.length} @${slope.segment} %)` : ''}`
|
||||
];
|
||||
|
||||
if (elevationFill === 'surface') {
|
||||
labels.push(
|
||||
` ${$_('quantities.surface')}: ${$_(`toolbar.routing.surface.${surface}`)}`
|
||||
);
|
||||
}
|
||||
|
||||
if (elevationFill === 'highway') {
|
||||
labels.push(
|
||||
` ${$_('quantities.highway')}: ${$_(`toolbar.routing.highway.${highway}`)}${
|
||||
sacScale ? ` (${$_(`toolbar.routing.sac_scale.${sacScale}`)})` : ''
|
||||
}`
|
||||
);
|
||||
if (mtbScale) {
|
||||
labels.push(` ${$_('toolbar.routing.mtb_scale')}: ${mtbScale}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (point.time) {
|
||||
labels.push(` ${$_('quantities.time')}: ${df.format(point.time)}`);
|
||||
}
|
||||
|
||||
return labels;
|
||||
}
|
||||
}
|
||||
},
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x',
|
||||
modifierKey: 'shift',
|
||||
onPanStart: function () {
|
||||
// hide tooltip
|
||||
panning = true;
|
||||
$slicedGPXStatistics = undefined;
|
||||
},
|
||||
onPanComplete: function () {
|
||||
panning = false;
|
||||
}
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true
|
||||
},
|
||||
mode: 'x',
|
||||
onZoomStart: function ({ chart, event }: { chart: Chart; event: any }) {
|
||||
if (
|
||||
event.deltaY < 0 &&
|
||||
Math.abs(
|
||||
chart.getInitialScaleBounds().x.max / chart.options.plugins.zoom.limits.x.minRange -
|
||||
chart.getZoomLevel()
|
||||
) < 0.01
|
||||
) {
|
||||
// Disable wheel pan if zoomed in to the max, and zooming in
|
||||
return false;
|
||||
}
|
||||
|
||||
$slicedGPXStatistics = undefined;
|
||||
}
|
||||
},
|
||||
limits: {
|
||||
x: {
|
||||
min: 'original',
|
||||
max: 'original',
|
||||
minRange: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
stacked: false,
|
||||
onResize: function () {
|
||||
updateOverlay();
|
||||
}
|
||||
};
|
||||
|
||||
let datasets: string[] = ['speed', 'hr', 'cad', 'atemp', 'power'];
|
||||
datasets.forEach((id) => {
|
||||
options.scales[`y${id}`] = {
|
||||
type: 'linear',
|
||||
position: 'right',
|
||||
grid: {
|
||||
display: false
|
||||
},
|
||||
reverse: () => id === 'speed' && $velocityUnits === 'pace',
|
||||
display: false
|
||||
};
|
||||
});
|
||||
|
||||
onMount(async () => {
|
||||
Chart.register((await import('chartjs-plugin-zoom')).default); // dynamic import to avoid SSR and 'window is not defined' error
|
||||
|
||||
chart = new Chart(canvas, {
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: []
|
||||
},
|
||||
options,
|
||||
plugins: [
|
||||
{
|
||||
id: 'toggleMarker',
|
||||
events: ['mouseout'],
|
||||
afterEvent: function (chart: Chart, args: { event: Chart.ChartEvent }) {
|
||||
if (args.event.type === 'mouseout') {
|
||||
if ($map && marker) {
|
||||
marker.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Map marker to show on hover
|
||||
let element = document.createElement('div');
|
||||
element.className = 'h-4 w-4 rounded-full bg-cyan-500 border-2 border-white';
|
||||
marker = new mapboxgl.Marker({
|
||||
element
|
||||
});
|
||||
|
||||
let startIndex = 0;
|
||||
let endIndex = 0;
|
||||
function getIndex(evt) {
|
||||
const points = chart.getElementsAtEventForMode(
|
||||
evt,
|
||||
'x',
|
||||
{
|
||||
intersect: false
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
if (points.length === 0) {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
if (evt.x - rect.left <= chart.chartArea.left) {
|
||||
return 0;
|
||||
} else if (evt.x - rect.left >= chart.chartArea.right) {
|
||||
return $gpxStatistics.local.points.length - 1;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
let point = points.find((point) => point.element.raw);
|
||||
if (point) {
|
||||
return point.element.raw.index;
|
||||
} else {
|
||||
return points[0].index;
|
||||
}
|
||||
}
|
||||
|
||||
let dragStarted = false;
|
||||
function onMouseDown(evt) {
|
||||
if (evt.shiftKey) {
|
||||
// Panning interaction
|
||||
return;
|
||||
}
|
||||
dragStarted = true;
|
||||
canvas.style.cursor = 'col-resize';
|
||||
startIndex = getIndex(evt);
|
||||
}
|
||||
function onMouseMove(evt) {
|
||||
if (dragStarted) {
|
||||
dragging = true;
|
||||
endIndex = getIndex(evt);
|
||||
if (endIndex !== undefined) {
|
||||
if (startIndex === undefined) {
|
||||
startIndex = endIndex;
|
||||
} else if (startIndex !== endIndex) {
|
||||
$slicedGPXStatistics = [
|
||||
$gpxStatistics.slice(Math.min(startIndex, endIndex), Math.max(startIndex, endIndex)),
|
||||
Math.min(startIndex, endIndex),
|
||||
Math.max(startIndex, endIndex)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function onMouseUp(evt) {
|
||||
dragStarted = false;
|
||||
dragging = false;
|
||||
canvas.style.cursor = '';
|
||||
endIndex = getIndex(evt);
|
||||
if (startIndex === endIndex) {
|
||||
$slicedGPXStatistics = undefined;
|
||||
}
|
||||
}
|
||||
canvas.addEventListener('pointerdown', onMouseDown);
|
||||
canvas.addEventListener('pointermove', onMouseMove);
|
||||
canvas.addEventListener('pointerup', onMouseUp);
|
||||
});
|
||||
|
||||
$: if (chart && $distanceUnits && $velocityUnits && $temperatureUnits) {
|
||||
let data = $gpxStatistics;
|
||||
|
||||
// update data
|
||||
chart.data.datasets[0] = {
|
||||
label: $_('quantities.elevation'),
|
||||
data: data.local.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(data.local.distance.total[index]),
|
||||
y: point.ele ? getConvertedElevation(point.ele) : 0,
|
||||
time: point.time,
|
||||
slope: {
|
||||
at: data.local.slope.at[index],
|
||||
segment: data.local.slope.segment[index],
|
||||
length: data.local.slope.length[index]
|
||||
},
|
||||
extensions: point.getExtensions(),
|
||||
coordinates: point.getCoordinates(),
|
||||
index: index
|
||||
};
|
||||
}),
|
||||
normalized: true,
|
||||
fill: 'start',
|
||||
order: 1
|
||||
};
|
||||
chart.data.datasets[1] = {
|
||||
data: data.local.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(data.local.distance.total[index]),
|
||||
y: getConvertedVelocity(data.local.speed[index]),
|
||||
index: index
|
||||
};
|
||||
}),
|
||||
normalized: true,
|
||||
yAxisID: 'yspeed',
|
||||
hidden: true
|
||||
};
|
||||
chart.data.datasets[2] = {
|
||||
data: data.local.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(data.local.distance.total[index]),
|
||||
y: point.getHeartRate(),
|
||||
index: index
|
||||
};
|
||||
}),
|
||||
normalized: true,
|
||||
yAxisID: 'yhr',
|
||||
hidden: true
|
||||
};
|
||||
chart.data.datasets[3] = {
|
||||
data: data.local.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(data.local.distance.total[index]),
|
||||
y: point.getCadence(),
|
||||
index: index
|
||||
};
|
||||
}),
|
||||
normalized: true,
|
||||
yAxisID: 'ycad',
|
||||
hidden: true
|
||||
};
|
||||
chart.data.datasets[4] = {
|
||||
data: data.local.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(data.local.distance.total[index]),
|
||||
y: getConvertedTemperature(point.getTemperature()),
|
||||
index: index
|
||||
};
|
||||
}),
|
||||
normalized: true,
|
||||
yAxisID: 'yatemp',
|
||||
hidden: true
|
||||
};
|
||||
chart.data.datasets[5] = {
|
||||
data: data.local.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(data.local.distance.total[index]),
|
||||
y: point.getPower(),
|
||||
index: index
|
||||
};
|
||||
}),
|
||||
normalized: true,
|
||||
yAxisID: 'ypower',
|
||||
hidden: true
|
||||
};
|
||||
chart.options.scales.x['min'] = 0;
|
||||
chart.options.scales.x['max'] = getConvertedDistance(data.global.distance.total);
|
||||
|
||||
chart.update();
|
||||
}
|
||||
|
||||
function slopeFillCallback(context) {
|
||||
return getSlopeColor(context.p0.raw.slope.segment);
|
||||
}
|
||||
|
||||
function surfaceFillCallback(context) {
|
||||
return getSurfaceColor(context.p0.raw.extensions.surface);
|
||||
}
|
||||
|
||||
function highwayFillCallback(context) {
|
||||
return getHighwayColor(
|
||||
context.p0.raw.extensions.highway,
|
||||
context.p0.raw.extensions.sac_scale,
|
||||
context.p0.raw.extensions.mtb_scale
|
||||
);
|
||||
}
|
||||
|
||||
$: if (chart) {
|
||||
if (elevationFill === 'slope') {
|
||||
chart.data.datasets[0]['segment'] = {
|
||||
backgroundColor: slopeFillCallback
|
||||
};
|
||||
} else if (elevationFill === 'surface') {
|
||||
chart.data.datasets[0]['segment'] = {
|
||||
backgroundColor: surfaceFillCallback
|
||||
};
|
||||
} else if (elevationFill === 'highway') {
|
||||
chart.data.datasets[0]['segment'] = {
|
||||
backgroundColor: highwayFillCallback
|
||||
};
|
||||
} else {
|
||||
chart.data.datasets[0]['segment'] = {};
|
||||
}
|
||||
chart.update();
|
||||
}
|
||||
|
||||
$: if (additionalDatasets && chart) {
|
||||
let includeSpeed = additionalDatasets.includes('speed');
|
||||
let includeHeartRate = additionalDatasets.includes('hr');
|
||||
let includeCadence = additionalDatasets.includes('cad');
|
||||
let includeTemperature = additionalDatasets.includes('atemp');
|
||||
let includePower = additionalDatasets.includes('power');
|
||||
if (chart.data.datasets.length > 0) {
|
||||
chart.data.datasets[1].hidden = !includeSpeed;
|
||||
chart.data.datasets[2].hidden = !includeHeartRate;
|
||||
chart.data.datasets[3].hidden = !includeCadence;
|
||||
chart.data.datasets[4].hidden = !includeTemperature;
|
||||
chart.data.datasets[5].hidden = !includePower;
|
||||
}
|
||||
chart.update();
|
||||
}
|
||||
|
||||
function updateOverlay() {
|
||||
if (!canvas) {
|
||||
return;
|
||||
}
|
||||
|
||||
overlay.width = canvas.width / window.devicePixelRatio;
|
||||
overlay.height = canvas.height / window.devicePixelRatio;
|
||||
overlay.style.width = `${overlay.width}px`;
|
||||
overlay.style.height = `${overlay.height}px`;
|
||||
|
||||
if ($slicedGPXStatistics) {
|
||||
let startIndex = $slicedGPXStatistics[1];
|
||||
let endIndex = $slicedGPXStatistics[2];
|
||||
|
||||
// Draw selection rectangle
|
||||
let selectionContext = overlay.getContext('2d');
|
||||
if (selectionContext) {
|
||||
selectionContext.fillStyle = $mode === 'dark' ? 'white' : 'black';
|
||||
selectionContext.globalAlpha = $mode === 'dark' ? 0.2 : 0.1;
|
||||
selectionContext.clearRect(0, 0, overlay.width, overlay.height);
|
||||
|
||||
let startPixel = chart.scales.x.getPixelForValue(
|
||||
getConvertedDistance($gpxStatistics.local.distance.total[startIndex])
|
||||
);
|
||||
let endPixel = chart.scales.x.getPixelForValue(
|
||||
getConvertedDistance($gpxStatistics.local.distance.total[endIndex])
|
||||
);
|
||||
|
||||
selectionContext.fillRect(
|
||||
startPixel,
|
||||
chart.chartArea.top,
|
||||
endPixel - startPixel,
|
||||
chart.chartArea.height
|
||||
);
|
||||
}
|
||||
} else if (overlay) {
|
||||
let selectionContext = overlay.getContext('2d');
|
||||
if (selectionContext) {
|
||||
selectionContext.clearRect(0, 0, overlay.width, overlay.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$: $slicedGPXStatistics, $mode, updateOverlay();
|
||||
|
||||
onDestroy(() => {
|
||||
if (chart) {
|
||||
chart.destroy();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="h-full grow min-w-0 relative py-2">
|
||||
<canvas bind:this={overlay} class="w-full h-full absolute pointer-events-none"></canvas>
|
||||
<canvas bind:this={canvas} class="w-full h-full absolute"></canvas>
|
||||
{#if showControls}
|
||||
<div class="absolute bottom-10 right-1.5">
|
||||
<Popover.Root>
|
||||
<Popover.Trigger asChild let:builder>
|
||||
<ButtonWithTooltip
|
||||
label={$_('chart.settings')}
|
||||
builders={[builder]}
|
||||
variant="outline"
|
||||
class="w-7 h-7 p-0 flex justify-center opacity-70 hover:opacity-100 transition-opacity duration-300 hover:bg-background"
|
||||
>
|
||||
<ChartNoAxesColumn size="18" />
|
||||
</ButtonWithTooltip>
|
||||
</Popover.Trigger>
|
||||
<Popover.Content class="w-fit p-0 flex flex-col divide-y" side="top" sideOffset={-32}>
|
||||
<ToggleGroup.Root
|
||||
class="flex flex-col items-start gap-0 p-1"
|
||||
type="single"
|
||||
bind:value={elevationFill}
|
||||
>
|
||||
<ToggleGroup.Item
|
||||
class="p-0 pr-1.5 h-6 w-full rounded flex justify-start data-[state=on]:bg-background data-[state=on]:hover:bg-accent hover:bg-accent hover:text-foreground"
|
||||
value="slope"
|
||||
>
|
||||
<div class="w-6 flex justify-center items-center">
|
||||
{#if elevationFill === 'slope'}
|
||||
<Circle class="h-1.5 w-1.5 fill-current text-current" />
|
||||
{/if}
|
||||
</div>
|
||||
<TriangleRight size="15" class="mr-1" />
|
||||
{$_('quantities.slope')}
|
||||
</ToggleGroup.Item>
|
||||
<ToggleGroup.Item
|
||||
class="p-0 pr-1.5 h-6 w-full rounded flex justify-start data-[state=on]:bg-background data-[state=on]:hover:bg-accent hover:bg-accent hover:text-foreground"
|
||||
value="surface"
|
||||
variant="outline"
|
||||
>
|
||||
<div class="w-6 flex justify-center items-center">
|
||||
{#if elevationFill === 'surface'}
|
||||
<Circle class="h-1.5 w-1.5 fill-current text-current" />
|
||||
{/if}
|
||||
</div>
|
||||
<BrickWall size="15" class="mr-1" />
|
||||
{$_('quantities.surface')}
|
||||
</ToggleGroup.Item>
|
||||
<ToggleGroup.Item
|
||||
class="p-0 pr-1.5 h-6 w-full rounded flex justify-start data-[state=on]:bg-background data-[state=on]:hover:bg-accent hover:bg-accent hover:text-foreground"
|
||||
value="highway"
|
||||
variant="outline"
|
||||
>
|
||||
<div class="w-6 flex justify-center items-center">
|
||||
{#if elevationFill === 'highway'}
|
||||
<Circle class="h-1.5 w-1.5 fill-current text-current" />
|
||||
{/if}
|
||||
</div>
|
||||
<Construction size="15" class="mr-1" />
|
||||
{$_('quantities.highway')}
|
||||
</ToggleGroup.Item>
|
||||
</ToggleGroup.Root>
|
||||
<ToggleGroup.Root
|
||||
class="flex flex-col items-start gap-0 p-1"
|
||||
type="multiple"
|
||||
bind:value={additionalDatasets}
|
||||
>
|
||||
<ToggleGroup.Item
|
||||
class="p-0 pr-1.5 h-6 w-full rounded flex justify-start data-[state=on]:bg-background data-[state=on]:hover:bg-accent hover:bg-accent hover:text-foreground"
|
||||
value="speed"
|
||||
>
|
||||
<div class="w-6 flex justify-center items-center">
|
||||
{#if additionalDatasets.includes('speed')}
|
||||
<Check size="14" />
|
||||
{/if}
|
||||
</div>
|
||||
<Zap size="15" class="mr-1" />
|
||||
{$velocityUnits === 'speed' ? $_('quantities.speed') : $_('quantities.pace')}
|
||||
</ToggleGroup.Item>
|
||||
<ToggleGroup.Item
|
||||
class="p-0 pr-1.5 h-6 w-full rounded flex justify-start data-[state=on]:bg-background data-[state=on]:hover:bg-accent hover:bg-accent hover:text-foreground"
|
||||
value="hr"
|
||||
>
|
||||
<div class="w-6 flex justify-center items-center">
|
||||
{#if additionalDatasets.includes('hr')}
|
||||
<Check size="14" />
|
||||
{/if}
|
||||
</div>
|
||||
<HeartPulse size="15" class="mr-1" />
|
||||
{$_('quantities.heartrate')}
|
||||
</ToggleGroup.Item>
|
||||
<ToggleGroup.Item
|
||||
class="p-0 pr-1.5 h-6 w-full rounded flex justify-start data-[state=on]:bg-background data-[state=on]:hover:bg-accent hover:bg-accent hover:text-foreground"
|
||||
value="cad"
|
||||
>
|
||||
<div class="w-6 flex justify-center items-center">
|
||||
{#if additionalDatasets.includes('cad')}
|
||||
<Check size="14" />
|
||||
{/if}
|
||||
</div>
|
||||
<Orbit size="15" class="mr-1" />
|
||||
{$_('quantities.cadence')}
|
||||
</ToggleGroup.Item>
|
||||
<ToggleGroup.Item
|
||||
class="p-0 pr-1.5 h-6 w-full rounded flex justify-start data-[state=on]:bg-background data-[state=on]:hover:bg-accent hover:bg-accent hover:text-foreground"
|
||||
value="atemp"
|
||||
>
|
||||
<div class="w-6 flex justify-center items-center">
|
||||
{#if additionalDatasets.includes('atemp')}
|
||||
<Check size="14" />
|
||||
{/if}
|
||||
</div>
|
||||
<Thermometer size="15" class="mr-1" />
|
||||
{$_('quantities.temperature')}
|
||||
</ToggleGroup.Item>
|
||||
<ToggleGroup.Item
|
||||
class="p-0 pr-1.5 h-6 w-full rounded flex justify-start data-[state=on]:bg-background data-[state=on]:hover:bg-accent hover:bg-accent hover:text-foreground"
|
||||
value="power"
|
||||
>
|
||||
<div class="w-6 flex justify-center items-center">
|
||||
{#if additionalDatasets.includes('power')}
|
||||
<Check size="14" />
|
||||
{/if}
|
||||
</div>
|
||||
<SquareActivity size="15" class="mr-1" />
|
||||
{$_('quantities.power')}
|
||||
</ToggleGroup.Item>
|
||||
</ToggleGroup.Root>
|
||||
</Popover.Content>
|
||||
</Popover.Root>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,186 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
import { Checkbox } from '$lib/components/ui/checkbox';
|
||||
import { Separator } from '$lib/components/ui/separator';
|
||||
import { Dialog } from 'bits-ui';
|
||||
import {
|
||||
currentTool,
|
||||
exportAllFiles,
|
||||
exportSelectedFiles,
|
||||
ExportState,
|
||||
exportState,
|
||||
gpxStatistics
|
||||
} from '$lib/stores';
|
||||
import { fileObservers } from '$lib/db';
|
||||
import {
|
||||
Download,
|
||||
Zap,
|
||||
Earth,
|
||||
HeartPulse,
|
||||
Orbit,
|
||||
Thermometer,
|
||||
SquareActivity
|
||||
} from 'lucide-svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { selection } from './file-list/Selection';
|
||||
import { get } from 'svelte/store';
|
||||
import { GPXStatistics } from 'gpx';
|
||||
import { ListRootItem } from './file-list/FileList';
|
||||
|
||||
let open = false;
|
||||
let exportOptions: Record<string, boolean> = {
|
||||
time: true,
|
||||
hr: true,
|
||||
cad: true,
|
||||
atemp: true,
|
||||
power: true,
|
||||
extensions: true
|
||||
};
|
||||
let hide: Record<string, boolean> = {
|
||||
time: false,
|
||||
hr: false,
|
||||
cad: false,
|
||||
atemp: false,
|
||||
power: false,
|
||||
extensions: false
|
||||
};
|
||||
|
||||
$: if ($exportState !== ExportState.NONE) {
|
||||
open = true;
|
||||
$currentTool = null;
|
||||
|
||||
let statistics = $gpxStatistics;
|
||||
if ($exportState === ExportState.ALL) {
|
||||
statistics = Array.from($fileObservers.values())
|
||||
.map((file) => get(file)?.statistics)
|
||||
.reduce((acc, cur) => {
|
||||
if (cur !== undefined) {
|
||||
acc.mergeWith(cur.getStatisticsFor(new ListRootItem()));
|
||||
}
|
||||
return acc;
|
||||
}, new GPXStatistics());
|
||||
}
|
||||
|
||||
hide.time = statistics.global.time.total === 0;
|
||||
hide.hr = statistics.global.hr.count === 0;
|
||||
hide.cad = statistics.global.cad.count === 0;
|
||||
hide.atemp = statistics.global.atemp.count === 0;
|
||||
hide.power = statistics.global.power.count === 0;
|
||||
hide.extensions = Object.keys(statistics.global.extensions).length === 0;
|
||||
}
|
||||
|
||||
$: exclude = Object.keys(exportOptions).filter((key) => !exportOptions[key]);
|
||||
</script>
|
||||
|
||||
<Dialog.Root
|
||||
bind:open
|
||||
onOpenChange={(isOpen) => {
|
||||
if (!isOpen) {
|
||||
$exportState = ExportState.NONE;
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Dialog.Trigger class="hidden" />
|
||||
<Dialog.Portal>
|
||||
<Dialog.Content
|
||||
class="fixed left-[50%] top-[50%] z-50 w-fit max-w-full translate-x-[-50%] translate-y-[-50%] flex flex-col items-center gap-3 border bg-background p-3 shadow-lg rounded-md"
|
||||
>
|
||||
<div
|
||||
class="w-full flex flex-row items-center justify-center gap-4 border rounded-md p-2 bg-secondary"
|
||||
>
|
||||
<span>⚠️</span>
|
||||
<span class="max-w-[80%] text-sm">
|
||||
{$_('menu.support_message')}
|
||||
</span>
|
||||
</div>
|
||||
<div class="w-full flex flex-row flex-wrap gap-2">
|
||||
<Button class="bg-support grow" href="https://ko-fi.com/gpxstudio" target="_blank">
|
||||
{$_('menu.support_button')}
|
||||
<span class="ml-2">🙏</span>
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="grow"
|
||||
on:click={() => {
|
||||
if ($exportState === ExportState.SELECTION) {
|
||||
exportSelectedFiles(exclude);
|
||||
} else if ($exportState === ExportState.ALL) {
|
||||
exportAllFiles(exclude);
|
||||
}
|
||||
open = false;
|
||||
$exportState = ExportState.NONE;
|
||||
}}
|
||||
>
|
||||
<Download size="16" class="mr-1" />
|
||||
{#if $fileObservers.size === 1 || ($exportState === ExportState.SELECTION && $selection.size === 1)}
|
||||
{$_('menu.download_file')}
|
||||
{:else}
|
||||
{$_('menu.download_files')}
|
||||
{/if}
|
||||
</Button>
|
||||
</div>
|
||||
<div
|
||||
class="w-full max-w-xl flex flex-col items-center gap-2 {Object.values(hide).some((v) => !v)
|
||||
? ''
|
||||
: 'hidden'}"
|
||||
>
|
||||
<div class="w-full flex flex-row items-center gap-3">
|
||||
<div class="grow">
|
||||
<Separator />
|
||||
</div>
|
||||
<Label class="shrink-0">
|
||||
{$_('menu.export_options')}
|
||||
</Label>
|
||||
<div class="grow">
|
||||
<Separator />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row flex-wrap justify-center gap-x-6 gap-y-2">
|
||||
<div class="flex flex-row items-center gap-1.5 {hide.time ? 'hidden' : ''}">
|
||||
<Checkbox id="export-time" bind:checked={exportOptions.time} />
|
||||
<Label for="export-time" class="flex flex-row items-center gap-1">
|
||||
<Zap size="16" />
|
||||
{$_('quantities.time')}
|
||||
</Label>
|
||||
</div>
|
||||
<div class="flex flex-row items-center gap-1.5 {hide.extensions ? 'hidden' : ''}">
|
||||
<Checkbox id="export-extensions" bind:checked={exportOptions.extensions} />
|
||||
<Label for="export-extensions" class="flex flex-row items-center gap-1">
|
||||
<Earth size="16" />
|
||||
{$_('quantities.osm_extensions')}
|
||||
</Label>
|
||||
</div>
|
||||
<div class="flex flex-row items-center gap-1.5 {hide.hr ? 'hidden' : ''}">
|
||||
<Checkbox id="export-heartrate" bind:checked={exportOptions.hr} />
|
||||
<Label for="export-heartrate" class="flex flex-row items-center gap-1">
|
||||
<HeartPulse size="16" />
|
||||
{$_('quantities.heartrate')}
|
||||
</Label>
|
||||
</div>
|
||||
<div class="flex flex-row items-center gap-1.5 {hide.cad ? 'hidden' : ''}">
|
||||
<Checkbox id="export-cadence" bind:checked={exportOptions.cad} />
|
||||
<Label for="export-cadence" class="flex flex-row items-center gap-1">
|
||||
<Orbit size="16" />
|
||||
{$_('quantities.cadence')}
|
||||
</Label>
|
||||
</div>
|
||||
<div class="flex flex-row items-center gap-1.5 {hide.atemp ? 'hidden' : ''}">
|
||||
<Checkbox id="export-temperature" bind:checked={exportOptions.atemp} />
|
||||
<Label for="export-temperature" class="flex flex-row items-center gap-1">
|
||||
<Thermometer size="16" />
|
||||
{$_('quantities.temperature')}
|
||||
</Label>
|
||||
</div>
|
||||
<div class="flex flex-row items-center gap-1.5 {hide.power ? 'hidden' : ''}">
|
||||
<Checkbox id="export-power" bind:checked={exportOptions.power} />
|
||||
<Label for="export-power" class="flex flex-row items-center gap-1">
|
||||
<SquareActivity size="16" />
|
||||
{$_('quantities.power')}
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
</Dialog.Root>
|
||||
@@ -1,125 +1,119 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import LanguageSelect from '$lib/components/LanguageSelect.svelte';
|
||||
import ModeSwitch from '$lib/components/ModeSwitch.svelte';
|
||||
import Logo from '$lib/components/Logo.svelte';
|
||||
import { AtSign, BookOpenText, Heart, Home, Map } from 'lucide-svelte';
|
||||
import { _, locale } from 'svelte-i18n';
|
||||
import { AtSign, BookOpenText, Heart, House, Map } from '@lucide/svelte';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
</script>
|
||||
|
||||
<footer class="w-full">
|
||||
<div class="mx-6 border-t">
|
||||
<div class="mx-12 py-10 flex flex-row flex-wrap justify-between gap-x-10 gap-y-6">
|
||||
<footer class="w-full px-12 py-10 border-t flex flex-col items-center">
|
||||
<div class="w-full max-w-5xl flex flex-row flex-wrap justify-between gap-x-10 gap-y-6">
|
||||
<div class="grow flex flex-col items-start">
|
||||
<Logo class="h-8" width="153" />
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href="https://github.com/gpxstudio/gpx.studio/blob/main/LICENSE"
|
||||
target="_blank"
|
||||
>
|
||||
MIT © 2024 gpx.studio
|
||||
MIT © 2026 gpx.studio
|
||||
</Button>
|
||||
<LanguageSelect class="w-40 mt-3" />
|
||||
<div class="mt-3 flex flex-row gap-1.5">
|
||||
<LanguageSelect />
|
||||
<ModeSwitch />
|
||||
</div>
|
||||
</div>
|
||||
<div class="grow max-w-2xl flex flex-row flex-wrap justify-between gap-x-10 gap-y-6">
|
||||
<div class="flex flex-col items-start gap-1">
|
||||
<span class="font-semibold">{$_('homepage.website')}</span>
|
||||
<span class="font-semibold">{i18n._('homepage.website')}</span>
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
href={getURLForLanguage($locale, '/')}
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href={getURLForLanguage(i18n.lang, '/')}
|
||||
>
|
||||
<Home size="16" class="mr-1" />
|
||||
{$_('homepage.home')}
|
||||
<House size="16" />
|
||||
{i18n._('homepage.home')}
|
||||
</Button>
|
||||
<Button
|
||||
data-sveltekit-reload
|
||||
variant="link"
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href={getURLForLanguage(i18n.lang, '/app')}
|
||||
>
|
||||
<Map size="16" />
|
||||
{i18n._('homepage.app')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
href={getURLForLanguage($locale, '/app')}
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href={getURLForLanguage(i18n.lang, '/help')}
|
||||
>
|
||||
<Map size="16" class="mr-1" />
|
||||
{$_('homepage.app')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
href={getURLForLanguage($locale, '/help')}
|
||||
>
|
||||
<BookOpenText size="16" class="mr-1" />
|
||||
{$_('menu.help')}
|
||||
<BookOpenText size="16" />
|
||||
{i18n._('menu.help')}
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex flex-col items-start gap-1" id="contact">
|
||||
<span class="font-semibold">{$_('homepage.contact')}</span>
|
||||
<span class="font-semibold">{i18n._('homepage.contact')}</span>
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href="https://www.reddit.com/r/gpxstudio/"
|
||||
target="_blank"
|
||||
>
|
||||
<Logo company="reddit" class="h-4 mr-1 fill-muted-foreground" />
|
||||
{$_('homepage.reddit')}
|
||||
<Logo company="reddit" class="h-4 fill-muted-foreground" />
|
||||
{i18n._('homepage.reddit')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href="https://facebook.com/gpx.studio"
|
||||
target="_blank"
|
||||
>
|
||||
<Logo company="facebook" class="h-4 mr-1 fill-muted-foreground" />
|
||||
{$_('homepage.facebook')}
|
||||
<Logo company="facebook" class="h-4 fill-muted-foreground" />
|
||||
{i18n._('homepage.facebook')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
href="https://x.com/gpxstudio"
|
||||
target="_blank"
|
||||
>
|
||||
<Logo company="x" class="h-4 mr-1 fill-muted-foreground" />
|
||||
{$_('homepage.x')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href="mailto:hello@gpx.studio"
|
||||
target="_blank"
|
||||
>
|
||||
<AtSign size="16" class="mr-1" />
|
||||
{$_('homepage.email')}
|
||||
<AtSign size="16" />
|
||||
{i18n._('homepage.email')}
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex flex-col items-start gap-1">
|
||||
<span class="font-semibold">{$_('homepage.contribute')}</span>
|
||||
<span class="font-semibold">{i18n._('homepage.contribute')}</span>
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
href="https://ko-fi.com/gpxstudio"
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href="https://opencollective.com/gpxstudio"
|
||||
target="_blank"
|
||||
>
|
||||
<Heart size="16" class="mr-1" />
|
||||
{$_('menu.donate')}
|
||||
<Heart size="16" />
|
||||
{i18n._('menu.donate')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href="https://crowdin.com/project/gpxstudio"
|
||||
target="_blank"
|
||||
>
|
||||
<Logo company="crowdin" class="h-4 mr-1 fill-muted-foreground" />
|
||||
{$_('homepage.crowdin')}
|
||||
<Logo company="crowdin" class="h-4 fill-muted-foreground" />
|
||||
{i18n._('homepage.crowdin')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
class="h-6 px-0 text-muted-foreground"
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href="https://github.com/gpxstudio/gpx.studio"
|
||||
target="_blank"
|
||||
>
|
||||
<Logo company="github" class="h-4 mr-1 fill-muted-foreground" />
|
||||
{$_('homepage.github')}
|
||||
<Logo company="github" class="h-4 fill-muted-foreground" />
|
||||
{i18n._('homepage.github')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -3,80 +3,90 @@
|
||||
import Tooltip from '$lib/components/Tooltip.svelte';
|
||||
import WithUnits from '$lib/components/WithUnits.svelte';
|
||||
|
||||
import { MoveDownRight, MoveUpRight, Ruler, Timer, Zap } from 'lucide-svelte';
|
||||
import { MoveDownRight, MoveUpRight, Ruler, Timer, Zap } from '@lucide/svelte';
|
||||
|
||||
import { _ } from 'svelte-i18n';
|
||||
import type { GPXStatistics } from 'gpx';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import { settings } from '$lib/db';
|
||||
|
||||
export let gpxStatistics: Writable<GPXStatistics>;
|
||||
export let slicedGPXStatistics: Writable<[GPXStatistics, number, number] | undefined>;
|
||||
export let orientation: 'horizontal' | 'vertical';
|
||||
export let panelSize: number;
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
import type { GPXGlobalStatistics, GPXStatisticsGroup } from 'gpx';
|
||||
import type { Readable } from 'svelte/store';
|
||||
import { settings } from '$lib/logic/settings';
|
||||
|
||||
const { velocityUnits } = settings;
|
||||
|
||||
let statistics: GPXStatistics;
|
||||
let panelHeight: number = $state(0);
|
||||
let panelWidth: number = $state(0);
|
||||
|
||||
$: if ($slicedGPXStatistics !== undefined) {
|
||||
statistics = $slicedGPXStatistics[0];
|
||||
} else {
|
||||
statistics = $gpxStatistics;
|
||||
}
|
||||
let {
|
||||
gpxStatistics,
|
||||
slicedGPXStatistics,
|
||||
orientation,
|
||||
}: {
|
||||
gpxStatistics: Readable<GPXStatisticsGroup>;
|
||||
slicedGPXStatistics: Readable<[GPXGlobalStatistics, number, number] | undefined>;
|
||||
orientation: 'horizontal' | 'vertical';
|
||||
} = $props();
|
||||
|
||||
let statistics = $derived(
|
||||
$slicedGPXStatistics !== undefined ? $slicedGPXStatistics[0] : $gpxStatistics.global
|
||||
);
|
||||
</script>
|
||||
|
||||
<Card.Root
|
||||
class="h-full {orientation === 'vertical'
|
||||
? 'min-w-40 sm:min-w-44 text-sm sm:text-base'
|
||||
: 'w-full'} border-none shadow-none"
|
||||
? 'min-w-40 sm:min-w-44'
|
||||
: 'w-full h-fit my-1'} ring-0 p-0 text-sm sm:text-base bg-transparent"
|
||||
>
|
||||
<Card.Content
|
||||
class="h-full flex {orientation === 'vertical'
|
||||
? 'flex-col justify-center'
|
||||
: 'flex-row w-full justify-between'} gap-4 p-0"
|
||||
<Card.Content class="h-full p-0">
|
||||
<div
|
||||
bind:clientHeight={panelHeight}
|
||||
bind:clientWidth={panelWidth}
|
||||
class="flex {orientation === 'vertical'
|
||||
? 'flex-col h-full justify-center'
|
||||
: 'flex-row w-full justify-evenly'} gap-4"
|
||||
>
|
||||
<Tooltip label={$_('quantities.distance')}>
|
||||
<Tooltip label={i18n._('quantities.distance')}>
|
||||
<span class="flex flex-row items-center">
|
||||
<Ruler size="16" class="mr-1" />
|
||||
<WithUnits value={statistics.global.distance.total} type="distance" />
|
||||
<WithUnits value={statistics.distance.total} type="distance" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip label={$_('quantities.elevation_gain_loss')}>
|
||||
<Tooltip label={i18n._('quantities.elevation_gain_loss')}>
|
||||
<span class="flex flex-row items-center">
|
||||
<MoveUpRight size="16" class="mr-1" />
|
||||
<WithUnits value={statistics.global.elevation.gain} type="elevation" />
|
||||
<WithUnits value={statistics.elevation.gain} type="elevation" />
|
||||
<MoveDownRight size="16" class="mx-1" />
|
||||
<WithUnits value={statistics.global.elevation.loss} type="elevation" />
|
||||
<WithUnits value={statistics.elevation.loss} type="elevation" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
{#if panelSize > 120 || orientation === 'horizontal'}
|
||||
{#if panelHeight > 120 || (orientation === 'horizontal' && panelWidth > 450)}
|
||||
<Tooltip
|
||||
class={orientation === 'horizontal' ? 'hidden xs:block' : ''}
|
||||
label="{$velocityUnits === 'speed' ? $_('quantities.speed') : $_('quantities.pace')} ({$_(
|
||||
'quantities.moving'
|
||||
)} / {$_('quantities.total')})"
|
||||
label="{$velocityUnits === 'speed'
|
||||
? i18n._('quantities.speed')
|
||||
: i18n._('quantities.pace')} ({i18n._('quantities.moving')} / {i18n._(
|
||||
'quantities.total'
|
||||
)})"
|
||||
>
|
||||
<span class="flex flex-row items-center">
|
||||
<Zap size="16" class="mr-1" />
|
||||
<WithUnits value={statistics.global.speed.moving} type="speed" showUnits={false} />
|
||||
<WithUnits value={statistics.speed.moving} type="speed" showUnits={false} />
|
||||
<span class="mx-1">/</span>
|
||||
<WithUnits value={statistics.global.speed.total} type="speed" />
|
||||
<WithUnits value={statistics.speed.total} type="speed" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
{/if}
|
||||
{#if panelSize > 160 || orientation === 'horizontal'}
|
||||
{#if panelHeight > 150 || (orientation === 'horizontal' && panelWidth > 620)}
|
||||
<Tooltip
|
||||
class={orientation === 'horizontal' ? 'hidden md:block' : ''}
|
||||
label="{$_('quantities.time')} ({$_('quantities.moving')} / {$_('quantities.total')})"
|
||||
label="{i18n._('quantities.time')} ({i18n._('quantities.moving')} / {i18n._(
|
||||
'quantities.total'
|
||||
)})"
|
||||
>
|
||||
<span class="flex flex-row items-center">
|
||||
<Timer size="16" class="mr-1" />
|
||||
<WithUnits value={statistics.global.time.moving} type="time" />
|
||||
<WithUnits value={statistics.time.moving} type="time" />
|
||||
<span class="mx-1">/</span>
|
||||
<WithUnits value={statistics.global.time.total} type="time" />
|
||||
<WithUnits value={statistics.time.total} type="time" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
{/if}
|
||||
</div>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
<script lang="ts">
|
||||
import { CircleHelp } from 'lucide-svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { CircleQuestionMark } from '@lucide/svelte';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
export let link: string | undefined = undefined;
|
||||
let {
|
||||
link,
|
||||
class: className = '',
|
||||
children,
|
||||
}: {
|
||||
link: string;
|
||||
class?: string;
|
||||
children: Snippet;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="text-sm bg-secondary rounded border flex flex-row items-center p-2 {$$props.class || ''}"
|
||||
>
|
||||
<CircleHelp size="16" class="w-4 mr-2 shrink-0 grow-0" />
|
||||
<div class="text-[13px] bg-secondary rounded border flex flex-row items-center p-2 {className}">
|
||||
<CircleQuestionMark size="16" class="w-4 mr-2 shrink-0 grow-0" />
|
||||
<div>
|
||||
<slot />
|
||||
{@render children()}
|
||||
{#if link}
|
||||
<a href={link} target="_blank" class="text-sm text-link hover:underline">
|
||||
{$_('menu.more')}
|
||||
<a href={link} target="_blank" class="text-[13px] text-link hover:underline">
|
||||
{i18n._('menu.more')}
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,51 +1,30 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import * as Select from '$lib/components/ui/select';
|
||||
import { languages } from '$lib/languages';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import { Languages } from 'lucide-svelte';
|
||||
import { _, locale } from 'svelte-i18n';
|
||||
|
||||
let selected = {
|
||||
value: '',
|
||||
label: ''
|
||||
};
|
||||
|
||||
$: if ($locale) {
|
||||
selected = {
|
||||
value: $locale,
|
||||
label: languages[$locale]
|
||||
};
|
||||
}
|
||||
import { Languages } from '@lucide/svelte';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
</script>
|
||||
|
||||
<Select.Root bind:selected>
|
||||
<Select.Trigger class="w-[180px] {$$props.class ?? ''}" aria-label={$_('menu.language')}>
|
||||
<Select.Root type="single" value={i18n.lang}>
|
||||
<Select.Trigger class="w-[180px] px-2" aria-label={i18n._('menu.language')}>
|
||||
<Languages size="16" />
|
||||
<Select.Value class="ml-2 mr-auto" />
|
||||
<span class="mr-auto">
|
||||
{languages[i18n.lang]}
|
||||
</span>
|
||||
</Select.Trigger>
|
||||
<Select.Content>
|
||||
{#each Object.entries(languages) as [lang, label]}
|
||||
{#if $page.url.pathname.includes('404')}
|
||||
{#if page.url.pathname.includes('404')}
|
||||
<a href={getURLForLanguage(lang, '/')}>
|
||||
<Select.Item value={lang}>{label}</Select.Item>
|
||||
</a>
|
||||
{:else}
|
||||
<a href={getURLForLanguage(lang, $page.url.pathname)}>
|
||||
<a href={getURLForLanguage(lang, page.url.pathname)}>
|
||||
<Select.Item value={lang}>{label}</Select.Item>
|
||||
</a>
|
||||
{/if}
|
||||
{/each}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
|
||||
<!-- hidden links for svelte crawling -->
|
||||
<div class="hidden">
|
||||
{#if !$page.url.pathname.includes('404')}
|
||||
{#each Object.entries(languages) as [lang, label]}
|
||||
<a href={getURLForLanguage(lang, $page.url.pathname)}>
|
||||
{label}
|
||||
</a>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,31 +1,30 @@
|
||||
<script lang="ts">
|
||||
import { mode } from 'mode-watcher';
|
||||
import { base } from '$app/paths';
|
||||
import { mode, systemPrefersMode } from 'mode-watcher';
|
||||
|
||||
export let iconOnly = false;
|
||||
export let company = 'gpx.studio';
|
||||
|
||||
$: effectiveMode = $mode ?? $systemPrefersMode ?? 'light';
|
||||
let {
|
||||
iconOnly = false,
|
||||
company = 'gpx.studio',
|
||||
...others
|
||||
}: {
|
||||
iconOnly?: boolean;
|
||||
company?: 'gpx.studio' | 'github' | 'crowdin' | 'facebook' | 'reddit';
|
||||
[key: string]: any;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
{#if company === 'gpx.studio'}
|
||||
<img
|
||||
src="{base}/{iconOnly ? 'icon' : 'logo'}{effectiveMode === 'dark' ? '-dark' : ''}.svg"
|
||||
src="{base}/{iconOnly ? 'icon' : 'logo'}{mode.current === 'dark' ? '-dark' : ''}.svg"
|
||||
alt="Logo of gpx.studio."
|
||||
{...$$restProps}
|
||||
/>
|
||||
{:else if company === 'mapbox'}
|
||||
<img
|
||||
src="{base}/mapbox-logo-{effectiveMode === 'dark' ? 'white' : 'black'}.svg"
|
||||
alt="Logo of Mapbox."
|
||||
{...$$restProps}
|
||||
{...others}
|
||||
/>
|
||||
{:else if company === 'github'}
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="fill-foreground {$$restProps.class ?? ''}"
|
||||
class="fill-foreground {others.class ?? ''}"
|
||||
><title>GitHub</title><path
|
||||
d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
|
||||
/></svg
|
||||
@@ -35,7 +34,7 @@
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="fill-foreground {$$restProps.class ?? ''}"
|
||||
class="fill-foreground {others.class ?? ''}"
|
||||
><title>Crowdin</title><path
|
||||
d="M16.119 17.793a2.619 2.619 0 0 1-1.667-.562c-.546-.436-1.004-1.09-1.018-1.858-.008-.388.414-.388.414-.388l1.018-.008c.332.008.43.47.445.586.128 1.04.717 1.495 1.168 1.702.273.123.204.513-.362.528zm-5.695-5.287L8.5 12.252c-.867-.214-.844-.982-.807-1.247a5.119 5.119 0 0 1 .814-2.125c.545-.804 1.303-1.508 2.29-2.073 1.856-1.074 4.45-1.673 7.31-1.673 2.09 0 4.256.27 4.29.27.197.025.328.213.333.437a.377.377 0 0 1-.355.393l-.92-.01c-2.902 0-4.968.394-6.506 1.248-1.527.837-2.57 2.117-3.287 4.012-.076.163-.335 1.12-1.24 1.022zm2.533 7.823c-1.44 0-2.797-.622-3.825-1.746-.87-.96-1.397-1.931-1.493-3.164-.06-.813.3-1.094.788-1.044l1.988.218c.45.092.75.34.825.854.397 2.736 2.122 3.814 3.15 4.046.18.042.292.157.283.365a.412.412 0 0 1-.322.398c-.458.074-.936.073-1.394.073zm-4.101 2.418a14.216 14.216 0 0 1-2.307-.214c-1.202-.214-2.208-.582-3.072-1.13C1.41 20.095.163 17.786.014 15.048c-.037-.65-.11-1.89 1.427-1.797.638.033 1.653.343 2.368.548.887.247 1.314.933 1.314 1.608 0 3.858 3.494 6.408 5.02 6.408.654 0 .414.701.127.779-.502.136-1.15.153-1.413.153zM3.525 11.419c-.605-.109-1.194-.358-1.768-.5C-.018 10.479.284 8.688.45 8.196c1.617-4.757 6.746-6.35 10.887-6.773 3.898-.4 7.978-.092 11.778.967.31.083 1.269.327.718.891-.35.358-1.7-.016-2.073-.041-2.23-.167-4.434-.192-6.656.15-2.349.357-4.768 1.099-6.71 2.665-.938.758-1.76 1.723-2.313 2.866-.144.3-.256.6-.354.9-.11.327-.47 1.91-2.215 1.6zm9.94.917c.332-1.488 1.81-3.848 6.385-3.686 1.05.033.57.749.052.731-2.586-.09-3.815 1.578-4.457 3.27-.219.546-.68.626-1.271.53-.415-.074-.866-.123-.71-.846Z"
|
||||
/></svg
|
||||
@@ -45,27 +44,17 @@
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="fill-foreground {$$restProps.class ?? ''}"
|
||||
class="fill-foreground {others.class ?? ''}"
|
||||
><title>Facebook</title><path
|
||||
d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z"
|
||||
/></svg
|
||||
>
|
||||
{:else if company === 'x'}
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="fill-foreground {$$restProps.class ?? ''}"
|
||||
><title>X</title><path
|
||||
d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"
|
||||
/></svg
|
||||
>
|
||||
{:else if company === 'reddit'}
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="fill-foreground {$$restProps.class ?? ''}"
|
||||
class="fill-foreground {others.class ?? ''}"
|
||||
><title>Reddit</title><path
|
||||
d="M12 0C5.373 0 0 5.373 0 12c0 3.314 1.343 6.314 3.515 8.485l-2.286 2.286C.775 23.225 1.097 24 1.738 24H12c6.627 0 12-5.373 12-12S18.627 0 12 0Zm4.388 3.199c1.104 0 1.999.895 1.999 1.999 0 1.105-.895 2-1.999 2-.946 0-1.739-.657-1.947-1.539v.002c-1.147.162-2.032 1.15-2.032 2.341v.007c1.776.067 3.4.567 4.686 1.363.473-.363 1.064-.58 1.707-.58 1.547 0 2.802 1.254 2.802 2.802 0 1.117-.655 2.081-1.601 2.531-.088 3.256-3.637 5.876-7.997 5.876-4.361 0-7.905-2.617-7.998-5.87-.954-.447-1.614-1.415-1.614-2.538 0-1.548 1.255-2.802 2.803-2.802.645 0 1.239.218 1.712.585 1.275-.79 2.881-1.291 4.64-1.365v-.01c0-1.663 1.263-3.034 2.88-3.207.188-.911.993-1.595 1.959-1.595Zm-8.085 8.376c-.784 0-1.459.78-1.506 1.797-.047 1.016.64 1.429 1.426 1.429.786 0 1.371-.369 1.418-1.385.047-1.017-.553-1.841-1.338-1.841Zm7.406 0c-.786 0-1.385.824-1.338 1.841.047 1.017.634 1.385 1.418 1.385.785 0 1.473-.413 1.426-1.429-.046-1.017-.721-1.797-1.506-1.797Zm-3.703 4.013c-.974 0-1.907.048-2.77.135-.147.015-.241.168-.183.305.483 1.154 1.622 1.964 2.953 1.964 1.33 0 2.47-.81 2.953-1.964.057-.137-.037-.29-.184-.305-.863-.087-1.795-.135-2.769-.135Z"
|
||||
/></svg
|
||||
|
||||
@@ -1,394 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
|
||||
import mapboxgl from 'mapbox-gl';
|
||||
import 'mapbox-gl/dist/mapbox-gl.css';
|
||||
|
||||
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
|
||||
import '@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css';
|
||||
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { map } from '$lib/stores';
|
||||
import { settings } from '$lib/db';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { PUBLIC_MAPBOX_TOKEN } from '$env/static/public';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
export let accessToken = PUBLIC_MAPBOX_TOKEN;
|
||||
export let geolocate = true;
|
||||
export let geocoder = true;
|
||||
export let hash = true;
|
||||
|
||||
mapboxgl.accessToken = accessToken;
|
||||
|
||||
let webgl2Supported = true;
|
||||
let fitBoundsOptions: mapboxgl.FitBoundsOptions = {
|
||||
maxZoom: 15,
|
||||
linear: true,
|
||||
easing: () => 1
|
||||
};
|
||||
|
||||
const { distanceUnits, elevationProfile, verticalFileView, bottomPanelSize, rightPanelSize } =
|
||||
settings;
|
||||
let scaleControl = new mapboxgl.ScaleControl({
|
||||
unit: $distanceUnits
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
let gl = document.createElement('canvas').getContext('webgl2');
|
||||
if (!gl) {
|
||||
webgl2Supported = false;
|
||||
return;
|
||||
}
|
||||
|
||||
let language = $page.params.language;
|
||||
if (language === 'zh') {
|
||||
language = 'zh-Hans';
|
||||
} else if (language?.includes('-')) {
|
||||
language = language.split('-')[0];
|
||||
} else if (language === '' || language === undefined) {
|
||||
language = 'en';
|
||||
}
|
||||
|
||||
const loadJson = mapboxgl.Style.prototype._load;
|
||||
mapboxgl.Style.prototype._load = function (json, validate) {
|
||||
if (
|
||||
json['sources'] &&
|
||||
json['sources']['mapbox-satellite'] &&
|
||||
json['sources']['mapbox-satellite']['data'] &&
|
||||
json['sources']['mapbox-satellite']['data']['data']
|
||||
) {
|
||||
// Temporary fix for https://github.com/gpxstudio/gpx.studio/issues/129
|
||||
delete json['sources']['mapbox-satellite']['data']['data'];
|
||||
}
|
||||
loadJson.call(this, json, validate);
|
||||
};
|
||||
|
||||
let newMap = new mapboxgl.Map({
|
||||
container: 'map',
|
||||
style: {
|
||||
version: 8,
|
||||
sources: {},
|
||||
layers: [],
|
||||
imports: [
|
||||
{
|
||||
id: 'glyphs-and-sprite', // make Mapbox glyphs and sprite available to other styles
|
||||
url: '',
|
||||
data: {
|
||||
version: 8,
|
||||
sources: {},
|
||||
layers: [],
|
||||
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
|
||||
sprite: `https://api.mapbox.com/styles/v1/mapbox/outdoors-v12/sprite?access_token=${PUBLIC_MAPBOX_TOKEN}`
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'basemap',
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
id: 'overlays',
|
||||
url: '',
|
||||
data: {
|
||||
version: 8,
|
||||
sources: {},
|
||||
layers: []
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
zoom: 0,
|
||||
hash: hash,
|
||||
language,
|
||||
attributionControl: false,
|
||||
logoPosition: 'bottom-right',
|
||||
boxZoom: false
|
||||
});
|
||||
newMap.on('load', () => {
|
||||
$map = newMap; // only set the store after the map has loaded
|
||||
window._map = newMap; // entry point for extensions
|
||||
scaleControl.setUnit($distanceUnits);
|
||||
});
|
||||
|
||||
newMap.addControl(
|
||||
new mapboxgl.AttributionControl({
|
||||
compact: true
|
||||
})
|
||||
);
|
||||
|
||||
newMap.addControl(
|
||||
new mapboxgl.NavigationControl({
|
||||
visualizePitch: true
|
||||
})
|
||||
);
|
||||
|
||||
if (geocoder) {
|
||||
let geocoder = new MapboxGeocoder({
|
||||
mapboxgl: mapboxgl,
|
||||
enableEventLogging: false,
|
||||
collapsed: true,
|
||||
flyTo: fitBoundsOptions,
|
||||
language,
|
||||
localGeocoder: () => [],
|
||||
localGeocoderOnly: true,
|
||||
externalGeocoder: (query: string) =>
|
||||
fetch(
|
||||
`https://nominatim.openstreetmap.org/search?format=json&q=${query}&limit=5&accept-language=${language}`
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
return data.map((result: any) => {
|
||||
return {
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [result.lon, result.lat]
|
||||
},
|
||||
place_name: result.display_name
|
||||
};
|
||||
});
|
||||
})
|
||||
});
|
||||
let onKeyDown = geocoder._onKeyDown;
|
||||
geocoder._onKeyDown = (e: KeyboardEvent) => {
|
||||
// Trigger search on Enter key only
|
||||
if (e.key === 'Enter') {
|
||||
onKeyDown.apply(geocoder, [{ target: geocoder._inputEl }]);
|
||||
} else if (geocoder._typeahead.data.length > 0) {
|
||||
geocoder._typeahead.clear();
|
||||
}
|
||||
};
|
||||
newMap.addControl(geocoder);
|
||||
}
|
||||
|
||||
if (geolocate) {
|
||||
newMap.addControl(
|
||||
new mapboxgl.GeolocateControl({
|
||||
positionOptions: {
|
||||
enableHighAccuracy: true
|
||||
},
|
||||
fitBoundsOptions,
|
||||
trackUserLocation: true,
|
||||
showUserHeading: true
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
newMap.addControl(scaleControl);
|
||||
|
||||
newMap.on('style.load', () => {
|
||||
newMap.addSource('mapbox-dem', {
|
||||
type: 'raster-dem',
|
||||
url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
|
||||
tileSize: 512,
|
||||
maxzoom: 14
|
||||
});
|
||||
if (newMap.getPitch() > 0) {
|
||||
newMap.setTerrain({
|
||||
source: 'mapbox-dem',
|
||||
exaggeration: 1
|
||||
});
|
||||
}
|
||||
newMap.setFog({
|
||||
color: 'rgb(186, 210, 235)',
|
||||
'high-color': 'rgb(36, 92, 223)',
|
||||
'horizon-blend': 0.1,
|
||||
'space-color': 'rgb(156, 240, 255)'
|
||||
});
|
||||
newMap.on('pitch', () => {
|
||||
if (newMap.getPitch() > 0) {
|
||||
newMap.setTerrain({
|
||||
source: 'mapbox-dem',
|
||||
exaggeration: 1
|
||||
});
|
||||
} else {
|
||||
newMap.setTerrain(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if ($map) {
|
||||
$map.remove();
|
||||
$map = null;
|
||||
}
|
||||
});
|
||||
|
||||
$: if (
|
||||
$map &&
|
||||
(!$verticalFileView || !$elevationProfile || $bottomPanelSize || $rightPanelSize)
|
||||
) {
|
||||
$map.resize();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div {...$$restProps}>
|
||||
<div id="map" class="h-full {webgl2Supported ? '' : 'hidden'}"></div>
|
||||
<div
|
||||
class="flex flex-col items-center justify-center gap-3 h-full {webgl2Supported ? 'hidden' : ''}"
|
||||
>
|
||||
<p>{$_('webgl2_required')}</p>
|
||||
<Button href="https://get.webgl.org/webgl2/" target="_blank">
|
||||
{$_('enable_webgl2')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
div :global(.mapboxgl-map) {
|
||||
@apply font-sans;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-top-right > .mapboxgl-ctrl) {
|
||||
@apply shadow-md;
|
||||
@apply bg-background;
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-icon) {
|
||||
@apply dark:brightness-[4.7];
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-geocoder) {
|
||||
@apply flex;
|
||||
@apply flex-row;
|
||||
@apply w-fit;
|
||||
@apply min-w-fit;
|
||||
@apply items-center;
|
||||
@apply shadow-md;
|
||||
}
|
||||
|
||||
div :global(.suggestions) {
|
||||
@apply shadow-md;
|
||||
@apply bg-background;
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-geocoder .suggestions > li > a) {
|
||||
@apply text-foreground;
|
||||
@apply hover:text-accent-foreground;
|
||||
@apply hover:bg-accent;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-geocoder .suggestions > .active > a) {
|
||||
@apply bg-background;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-geocoder--button) {
|
||||
@apply bg-transparent;
|
||||
@apply hover:bg-transparent;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-geocoder--icon) {
|
||||
@apply fill-foreground;
|
||||
@apply hover:fill-accent-foreground;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-geocoder--icon-search) {
|
||||
@apply relative;
|
||||
@apply top-0;
|
||||
@apply left-0;
|
||||
@apply my-2;
|
||||
@apply w-[29px];
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-geocoder--input) {
|
||||
@apply relative;
|
||||
@apply w-64;
|
||||
@apply py-0;
|
||||
@apply pl-2;
|
||||
@apply focus:outline-none;
|
||||
@apply transition-[width];
|
||||
@apply duration-200;
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-geocoder--collapsed .mapboxgl-ctrl-geocoder--input) {
|
||||
@apply w-0;
|
||||
@apply p-0;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-top-right) {
|
||||
@apply z-40;
|
||||
@apply flex;
|
||||
@apply flex-col;
|
||||
@apply items-end;
|
||||
@apply h-full;
|
||||
@apply overflow-hidden;
|
||||
}
|
||||
|
||||
.horizontal :global(.mapboxgl-ctrl-bottom-left) {
|
||||
@apply bottom-[42px];
|
||||
}
|
||||
|
||||
.horizontal :global(.mapboxgl-ctrl-bottom-right) {
|
||||
@apply bottom-[42px];
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-attrib) {
|
||||
@apply dark:bg-transparent;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-compact-show.mapboxgl-ctrl-attrib) {
|
||||
@apply dark:bg-background;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-attrib-button) {
|
||||
@apply dark:bg-foreground;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-compact-show .mapboxgl-ctrl-attrib-button) {
|
||||
@apply dark:bg-foreground;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-ctrl-attrib a) {
|
||||
@apply text-foreground;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-popup) {
|
||||
@apply w-fit;
|
||||
@apply z-50;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-popup-content) {
|
||||
@apply p-0;
|
||||
@apply bg-transparent;
|
||||
@apply shadow-none;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-popup-anchor-top .mapboxgl-popup-tip) {
|
||||
@apply border-b-background;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip) {
|
||||
@apply border-b-background;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip) {
|
||||
@apply border-b-background;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip) {
|
||||
@apply border-t-background;
|
||||
@apply drop-shadow-md;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip) {
|
||||
@apply border-t-background;
|
||||
@apply drop-shadow-md;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip) {
|
||||
@apply border-t-background;
|
||||
@apply drop-shadow-md;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-popup-anchor-left .mapboxgl-popup-tip) {
|
||||
@apply border-r-background;
|
||||
}
|
||||
|
||||
div :global(.mapboxgl-popup-anchor-right .mapboxgl-popup-tip) {
|
||||
@apply border-l-background;
|
||||
}
|
||||
</style>
|
||||
@@ -1,25 +0,0 @@
|
||||
<svelte:options accessors />
|
||||
|
||||
<script lang="ts">
|
||||
import { TrackPoint, Waypoint } from 'gpx';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import WaypointPopup from '$lib/components/gpx-layer/WaypointPopup.svelte';
|
||||
import TrackpointPopup from '$lib/components/gpx-layer/TrackpointPopup.svelte';
|
||||
import OverpassPopup from '$lib/components/layer-control/OverpassPopup.svelte';
|
||||
import type { PopupItem } from './MapPopup';
|
||||
|
||||
export let item: Writable<PopupItem | null>;
|
||||
export let container: HTMLDivElement | null = null;
|
||||
</script>
|
||||
|
||||
<div bind:this={container}>
|
||||
{#if $item}
|
||||
{#if $item.item instanceof Waypoint}
|
||||
<WaypointPopup waypoint={$item} />
|
||||
{:else if $item.item instanceof TrackPoint}
|
||||
<TrackpointPopup trackpoint={$item} />
|
||||
{:else}
|
||||
<OverpassPopup poi={$item} />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,78 +0,0 @@
|
||||
import { TrackPoint, Waypoint } from "gpx";
|
||||
import mapboxgl from "mapbox-gl";
|
||||
import { tick } from "svelte";
|
||||
import { get, writable, type Writable } from "svelte/store";
|
||||
import MapPopupComponent from "./MapPopup.svelte";
|
||||
|
||||
export type PopupItem<T = Waypoint | TrackPoint | any> = {
|
||||
item: T;
|
||||
fileId?: string;
|
||||
};
|
||||
|
||||
export class MapPopup {
|
||||
map: mapboxgl.Map;
|
||||
popup: mapboxgl.Popup;
|
||||
item: Writable<PopupItem | null> = writable(null);
|
||||
maybeHideBinded = this.maybeHide.bind(this);
|
||||
|
||||
constructor(map: mapboxgl.Map, options?: mapboxgl.PopupOptions) {
|
||||
this.map = map;
|
||||
this.popup = new mapboxgl.Popup(options);
|
||||
|
||||
let component = new MapPopupComponent({
|
||||
target: document.body,
|
||||
props: {
|
||||
item: this.item
|
||||
}
|
||||
});
|
||||
|
||||
tick().then(() => this.popup.setDOMContent(component.container));
|
||||
}
|
||||
|
||||
setItem(item: PopupItem | null) {
|
||||
this.item.set(item);
|
||||
if (item === null) {
|
||||
this.hide();
|
||||
} else {
|
||||
tick().then(() => this.show());
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
const i = get(this.item);
|
||||
if (i === null) {
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
this.popup.setLngLat(this.getCoordinates()).addTo(this.map);
|
||||
this.map.on('mousemove', this.maybeHideBinded);
|
||||
}
|
||||
|
||||
maybeHide(e: mapboxgl.MapMouseEvent) {
|
||||
const i = get(this.item);
|
||||
if (i === null) {
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
if (this.map.project(this.getCoordinates()).dist(this.map.project(e.lngLat)) > 60) {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.popup.remove();
|
||||
this.map.off('mousemove', this.maybeHideBinded);
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.popup.remove();
|
||||
}
|
||||
|
||||
getCoordinates() {
|
||||
const i = get(this.item);
|
||||
if (i === null) {
|
||||
return new mapboxgl.LngLat(0, 0);
|
||||
}
|
||||
return (i.item instanceof Waypoint || i.item instanceof TrackPoint) ? i.item.getCoordinates() : new mapboxgl.LngLat(i.item.lon, i.item.lat);
|
||||
}
|
||||
}
|
||||