Ticket #16681: GPXCorrelateV2.patch
| File GPXCorrelateV2.patch, 112.1 KB (added by , 7 years ago) |
|---|
-
data_nodist/ImageCorrelationTest.gpx
1 <?xml version='1.0' encoding='UTF-8'?> 2 <gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"> 5 <metadata> 6 <bounds minlat="47.1849004" minlon="8.7719297" maxlat="47.2014997" maxlon="8.7984188"/> 7 </metadata> 8 <trk> 9 <trkseg> 10 <trkpt lat="47.19286847859621" lon="8.79732714034617"> 11 <ele>471.86000000000001</ele> 12 <time>2016-01-03T11:59:58.000Z</time> 13 </trkpt> 14 <trkpt lat="47.192921955138445" lon="8.797342479228973"> 15 <ele>471.43000000000001</ele> 16 <time>2016-01-03T11:59:59.000Z</time> 17 </trkpt> 18 <trkpt lat="47.19297501258552" lon="8.79734423942864"> 19 <ele>470.69</ele> 20 <time>2016-01-03T12:00:00.000Z</time> 21 </trkpt> 22 <trkpt lat="47.19302739948034" lon="8.797332588583231"> 23 <ele>470.94</ele> 24 <time>2016-01-03T12:00:01.000Z</time> 25 </trkpt> 26 <trkpt lat="47.193073416128755" lon="8.797307442873716"> 27 <ele>471.5</ele> 28 <time>2016-01-03T12:00:02.000Z</time> 29 </trkpt> 30 <trkpt lat="47.193113481625915" lon="8.797272993251681"> 31 <ele>471.67000000000002</ele> 32 <time>2016-01-03T12:00:03.000Z</time> 33 </trkpt> 34 <trkpt lat="47.19313560985029" lon="8.797232424840331"> 35 <ele>471.58999999999997</ele> 36 <time>2016-01-03T12:00:04.000Z</time> 37 </trkpt> 38 <trkpt lat="47.19333660788834" lon="8.796738646924496"> 39 <ele>472.44999999999999</ele> 40 <time>2016-01-03T12:00:15.000Z</time> 41 </trkpt> 42 <trkpt lat="47.193504832684994" lon="8.796404711902142"> 43 <ele>472.54000000000002</ele> 44 <time>2016-01-03T12:00:22.000Z</time> 45 </trkpt> 46 <trkpt lat="47.19353936612606" lon="8.79635970108211"> 47 <ele>472.45999999999998</ele> 48 <time>2016-01-03T12:00:23.000Z</time> 49 </trkpt> 50 <trkpt lat="47.19381898641586" lon="8.796017384156585"> 51 <ele>471.38</ele> 52 <time>2016-01-03T12:00:30.000Z</time> 53 </trkpt> 54 <trkpt lat="47.19386676326394" lon="8.795985281467438"> 55 <ele>471.26999999999998</ele> 56 <time>2016-01-03T12:00:31.000Z</time> 57 </trkpt> 58 <trkpt lat="47.19391797669232" lon="8.795968098565936"> 59 <ele>471.36000000000001</ele> 60 <time>2016-01-03T12:00:32.000Z</time> 61 </trkpt> 62 <trkpt lat="47.19474418088794" lon="8.795836586505175"> 63 <ele>473.19999999999999</ele> 64 <time>2016-01-03T12:00:50.000Z</time> 65 </trkpt> 66 <trkpt lat="47.195586981251836" lon="8.795750420540571"> 67 <ele>475.06</ele> 68 <time>2016-01-03T12:01:09.000Z</time> 69 </trkpt> 70 <trkpt lat="47.19563358463347" lon="8.795769028365612"> 71 <ele>474.75</ele> 72 <time>2016-01-03T12:01:10.000Z</time> 73 </trkpt> 74 <trkpt lat="47.19567717052996" lon="8.795795682817698"> 75 <ele>474.62</ele> 76 <time>2016-01-03T12:01:11.000Z</time> 77 </trkpt> 78 <trkpt lat="47.195715978741646" lon="8.79583046771586"> 79 <ele>474.74000000000001</ele> 80 <time>2016-01-03T12:01:12.000Z</time> 81 </trkpt> 82 <trkpt lat="47.19575093127787" lon="8.79587598145008"> 83 <ele>474.06</ele> 84 <time>2016-01-03T12:01:13.000Z</time> 85 </trkpt> 86 <trkpt lat="47.19578169286251" lon="8.795927111059427"> 87 <ele>474</ele> 88 <time>2016-01-03T12:01:14.000Z</time> 89 </trkpt> 90 <trkpt lat="47.195808347314596" lon="8.795980839058757"> 91 <ele>474.58999999999997</ele> 92 <time>2016-01-03T12:01:15.000Z</time> 93 </trkpt> 94 <trkpt lat="47.195833241567016" lon="8.796036075800657"> 95 <ele>474.81999999999999</ele> 96 <time>2016-01-03T12:01:16.000Z</time> 97 </trkpt> 98 <trkpt lat="47.19628603197634" lon="8.797110635787249"> 99 <ele>476.29000000000002</ele> 100 <time>2016-01-03T12:01:35.000Z</time> 101 </trkpt> 102 <trkpt lat="47.19658995978534" lon="8.797826115041971"> 103 <ele>478.48000000000002</ele> 104 <time>2016-01-03T12:01:50.000Z</time> 105 </trkpt> 106 <trkpt lat="47.19703386537731" lon="8.798356018960476"> 107 <ele>481.02999999999997</ele> 108 <time>2016-01-03T12:02:06.000Z</time> 109 </trkpt> 110 <trkpt lat="47.19723687507212" lon="8.79841879941523"> 111 <ele>480</ele> 112 <time>2016-01-03T12:02:12.000Z</time> 113 </trkpt> 114 <trkpt lat="47.19727886840701" lon="8.79838845692575"> 115 <ele>479.58999999999997</ele> 116 <time>2016-01-03T12:02:13.000Z</time> 117 </trkpt> 118 <trkpt lat="47.19731541350484" lon="8.798339758068323"> 119 <ele>478.99000000000001</ele> 120 <time>2016-01-03T12:02:14.000Z</time> 121 </trkpt> 122 <trkpt lat="47.197333350777626" lon="8.798282761126757"> 123 <ele>479.58999999999997</ele> 124 <time>2016-01-03T12:02:15.000Z</time> 125 </trkpt> 126 <trkpt lat="47.19734919257462" lon="8.798161642625928"> 127 <ele>481.18000000000001</ele> 128 <time>2016-01-03T12:02:18.000Z</time> 129 </trkpt> 130 <trkpt lat="47.19734827056527" lon="8.798118894919753"> 131 <ele>481.88</ele> 132 <time>2016-01-03T12:02:20.000Z</time> 133 </trkpt> 134 <trkpt lat="47.19730585813522" lon="8.79802887327969"> 135 <ele>483.11000000000001</ele> 136 <time>2016-01-03T12:02:24.000Z</time> 137 </trkpt> 138 <trkpt lat="47.19727643765509" lon="8.79797455854714"> 139 <ele>484.49000000000001</ele> 140 <time>2016-01-03T12:02:27.000Z</time> 141 </trkpt> 142 <trkpt lat="47.19720158725977" lon="8.797768447548151"> 143 <ele>486.88</ele> 144 <time>2016-01-03T12:02:35.000Z</time> 145 </trkpt> 146 <trkpt lat="47.19708633609116" lon="8.79746401682496"> 147 <ele>488.05000000000001</ele> 148 <time>2016-01-03T12:02:48.000Z</time> 149 </trkpt> 150 <trkpt lat="47.19707007519901" lon="8.79741758108139"> 151 <ele>487.76999999999998</ele> 152 <time>2016-01-03T12:02:51.000Z</time> 153 </trkpt> 154 <trkpt lat="47.19702917151153" lon="8.797250529751182"> 155 <ele>488.95999999999998</ele> 156 <time>2016-01-03T12:02:57.000Z</time> 157 </trkpt> 158 <trkpt lat="47.19699899666011" lon="8.797172158956528"> 159 <ele>488.36000000000001</ele> 160 <time>2016-01-03T12:03:01.000Z</time> 161 </trkpt> 162 <trkpt lat="47.19691224396229" lon="8.796978034079075"> 163 <ele>488.35000000000002</ele> 164 <time>2016-01-03T12:03:09.000Z</time> 165 </trkpt> 166 <trkpt lat="47.19690545462072" lon="8.796931263059378"> 167 <ele>487.19</ele> 168 <time>2016-01-03T12:03:10.000Z</time> 169 </trkpt> 170 <trkpt lat="47.19690595753491" lon="8.796886671334505"> 171 <ele>487.63999999999999</ele> 172 <time>2016-01-03T12:03:11.000Z</time> 173 </trkpt> 174 <trkpt lat="47.19690511934459" lon="8.796837385743856"> 175 <ele>487.55000000000001</ele> 176 <time>2016-01-03T12:03:12.000Z</time> 177 </trkpt> 178 <trkpt lat="47.19690562225878" lon="8.796793716028333"> 179 <ele>488.39999999999998</ele> 180 <time>2016-01-03T12:03:13.000Z</time> 181 </trkpt> 182 <trkpt lat="47.196887601166964" lon="8.796751135960221"> 183 <ele>489.18000000000001</ele> 184 <time>2016-01-03T12:03:15.000Z</time> 185 </trkpt> 186 <trkpt lat="47.1968892775476" lon="8.796689361333847"> 187 <ele>490.73000000000002</ele> 188 <time>2016-01-03T12:03:18.000Z</time> 189 </trkpt> 190 <trkpt lat="47.196868155151606" lon="8.79647453315556"> 191 <ele>491.24000000000001</ele> 192 <time>2016-01-03T12:03:33.000Z</time> 193 </trkpt> 194 <trkpt lat="47.19686932861805" lon="8.796442430466413"> 195 <ele>490.25</ele> 196 <time>2016-01-03T12:03:34.000Z</time> 197 </trkpt> 198 <trkpt lat="47.19686849042773" lon="8.796406639739871"> 199 <ele>490.00999999999999</ele> 200 <time>2016-01-03T12:03:35.000Z</time> 201 </trkpt> 202 <trkpt lat="47.196873016655445" lon="8.796368166804314"> 203 <ele>489.54000000000002</ele> 204 <time>2016-01-03T12:03:36.000Z</time> 205 </trkpt> 206 <trkpt lat="47.19687905162573" lon="8.796329610049725"> 207 <ele>489.66000000000003</ele> 208 <time>2016-01-03T12:03:37.000Z</time> 209 </trkpt> 210 <trkpt lat="47.196886762976646" lon="8.796280743554235"> 211 <ele>489.06</ele> 212 <time>2016-01-03T12:03:38.000Z</time> 213 </trkpt> 214 <trkpt lat="47.19695775769651" lon="8.795829126611352"> 215 <ele>490.08999999999997</ele> 216 <time>2016-01-03T12:03:48.000Z</time> 217 </trkpt> 218 <trkpt lat="47.1969928778708" lon="8.795709516853094"> 219 <ele>489.41000000000003</ele> 220 <time>2016-01-03T12:03:52.000Z</time> 221 </trkpt> 222 <trkpt lat="47.19698550179601" lon="8.795667607337236"> 223 <ele>489.17000000000002</ele> 224 <time>2016-01-03T12:03:53.000Z</time> 225 </trkpt> 226 <trkpt lat="47.19697644934058" lon="8.795624608173966"> 227 <ele>488.87</ele> 228 <time>2016-01-03T12:03:54.000Z</time> 229 </trkpt> 230 <trkpt lat="47.19696890562773" lon="8.795590326189995"> 231 <ele>489.37</ele> 232 <time>2016-01-03T12:03:55.000Z</time> 233 </trkpt> 234 <trkpt lat="47.19696664251387" lon="8.795558391138911"> 235 <ele>488.94999999999999</ele> 236 <time>2016-01-03T12:03:56.000Z</time> 237 </trkpt> 238 <trkpt lat="47.19695256091654" lon="8.795536765828729"> 239 <ele>488.93000000000001</ele> 240 <time>2016-01-03T12:03:57.000Z</time> 241 </trkpt> 242 <trkpt lat="47.196956500411034" lon="8.795507680624723"> 243 <ele>488.88999999999999</ele> 244 <time>2016-01-03T12:03:58.000Z</time> 245 </trkpt> 246 <trkpt lat="47.19695859588683" lon="8.79548110999167"> 247 <ele>488.86000000000001</ele> 248 <time>2016-01-03T12:03:59.000Z</time> 249 </trkpt> 250 <trkpt lat="47.19696907326579" lon="8.795452527701855"> 251 <ele>489.19999999999999</ele> 252 <time>2016-01-03T12:04:00.000Z</time> 253 </trkpt> 254 <trkpt lat="47.19697988592088" lon="8.79541271366179"> 255 <ele>489.29000000000002</ele> 256 <time>2016-01-03T12:04:01.000Z</time> 257 </trkpt> 258 <trkpt lat="47.19698726199567" lon="8.795355297625065"> 259 <ele>488.95999999999998</ele> 260 <time>2016-01-03T12:04:02.000Z</time> 261 </trkpt> 262 <trkpt lat="47.19698960892856" lon="8.795302575454116"> 263 <ele>489.10000000000002</ele> 264 <time>2016-01-03T12:04:03.000Z</time> 265 </trkpt> 266 <trkpt lat="47.19690981321037" lon="8.79494265653193"> 267 <ele>492.19</ele> 268 <time>2016-01-03T12:04:14.000Z</time> 269 </trkpt> 270 <trkpt lat="47.19696622341871" lon="8.794532027095556"> 271 <ele>492.12</ele> 272 <time>2016-01-03T12:04:25.000Z</time> 273 </trkpt> 274 <trkpt lat="47.19697737134993" lon="8.79450285807252"> 275 <ele>493.06999999999999</ele> 276 <time>2016-01-03T12:04:26.000Z</time> 277 </trkpt> 278 <trkpt lat="47.19699212349951" lon="8.794450974091887"> 279 <ele>492.58999999999997</ele> 280 <time>2016-01-03T12:04:27.000Z</time> 281 </trkpt> 282 <trkpt lat="47.19699405133724" lon="8.794399006292224"> 283 <ele>492.38999999999999</ele> 284 <time>2016-01-03T12:04:28.000Z</time> 285 </trkpt> 286 <trkpt lat="47.19698860310018" lon="8.794350139796734"> 287 <ele>492.94</ele> 288 <time>2016-01-03T12:04:29.000Z</time> 289 </trkpt> 290 <trkpt lat="47.19698214903474" lon="8.794298926368356"> 291 <ele>492.47000000000003</ele> 292 <time>2016-01-03T12:04:30.000Z</time> 293 </trkpt> 294 <trkpt lat="47.19697737134993" lon="8.794246790930629"> 295 <ele>492.50999999999999</ele> 296 <time>2016-01-03T12:04:31.000Z</time> 297 </trkpt> 298 <trkpt lat="47.19698206521571" lon="8.794189291074872"> 299 <ele>492.73000000000002</ele> 300 <time>2016-01-03T12:04:32.000Z</time> 301 </trkpt> 302 <trkpt lat="47.196985417976975" lon="8.794133719056845"> 303 <ele>492.63</ele> 304 <time>2016-01-03T12:04:33.000Z</time> 305 </trkpt> 306 <trkpt lat="47.19698768109083" lon="8.794077644124627"> 307 <ele>493</ele> 308 <time>2016-01-03T12:04:34.000Z</time> 309 </trkpt> 310 <trkpt lat="47.19699136912823" lon="8.794022323563695"> 311 <ele>493.00999999999999</ele> 312 <time>2016-01-03T12:04:35.000Z</time> 313 </trkpt> 314 <trkpt lat="47.196987848728895" lon="8.793976558372378"> 315 <ele>493.19999999999999</ele> 316 <time>2016-01-03T12:04:36.000Z</time> 317 </trkpt> 318 <trkpt lat="47.19698550179601" lon="8.793926937505603"> 319 <ele>493.18000000000001</ele> 320 <time>2016-01-03T12:04:37.000Z</time> 321 </trkpt> 322 <trkpt lat="47.196980556473136" lon="8.793885698541999"> 323 <ele>493</ele> 324 <time>2016-01-03T12:04:38.000Z</time> 325 </trkpt> 326 <trkpt lat="47.19698307104409" lon="8.793837334960699"> 327 <ele>493.20999999999998</ele> 328 <time>2016-01-03T12:04:39.000Z</time> 329 </trkpt> 330 <trkpt lat="47.196992291137576" lon="8.793786959722638"> 331 <ele>493.11000000000001</ele> 332 <time>2016-01-03T12:04:40.000Z</time> 333 </trkpt> 334 <trkpt lat="47.19699547626078" lon="8.793743625283241"> 335 <ele>493.30000000000001</ele> 336 <time>2016-01-03T12:04:41.000Z</time> 337 </trkpt> 338 <trkpt lat="47.19700268469751" lon="8.793694507330656"> 339 <ele>493.50999999999999</ele> 340 <time>2016-01-03T12:04:42.000Z</time> 341 </trkpt> 342 <trkpt lat="47.19700511544943" lon="8.793357806280255"> 343 <ele>493</ele> 344 <time>2016-01-03T12:04:50.000Z</time> 345 </trkpt> 346 <trkpt lat="47.19702162779868" lon="8.793316148221493"> 347 <ele>492.37</ele> 348 <time>2016-01-03T12:04:51.000Z</time> 349 </trkpt> 350 <trkpt lat="47.19704459421337" lon="8.793262336403131"> 351 <ele>492.30000000000001</ele> 352 <time>2016-01-03T12:04:52.000Z</time> 353 </trkpt> 354 <trkpt lat="47.19706906937063" lon="8.793201064690948"> 355 <ele>492.04000000000002</ele> 356 <time>2016-01-03T12:04:53.000Z</time> 357 </trkpt> 358 <trkpt lat="47.19708985649049" lon="8.793123783543706"> 359 <ele>491.37</ele> 360 <time>2016-01-03T12:04:54.000Z</time> 361 </trkpt> 362 <trkpt lat="47.19710913486779" lon="8.79304625093937"> 363 <ele>491.06999999999999</ele> 364 <time>2016-01-03T12:04:55.000Z</time> 365 </trkpt> 366 <trkpt lat="47.19713117927313" lon="8.792974585667253"> 367 <ele>490.39999999999998</ele> 368 <time>2016-01-03T12:04:56.000Z</time> 369 </trkpt> 370 <trkpt lat="47.197186248376966" lon="8.792809881269932"> 371 <ele>489.75</ele> 372 <time>2016-01-03T12:04:58.000Z</time> 373 </trkpt> 374 <trkpt lat="47.19720753841102" lon="8.79271550104022"> 375 <ele>489.87</ele> 376 <time>2016-01-03T12:04:59.000Z</time> 377 </trkpt> 378 <trkpt lat="47.19722296111286" lon="8.792620282620192"> 379 <ele>488.95999999999998</ele> 380 <time>2016-01-03T12:05:00.000Z</time> 381 </trkpt> 382 <trkpt lat="47.19733930192888" lon="8.792043440043926"> 383 <ele>485.85000000000002</ele> 384 <time>2016-01-03T12:05:06.000Z</time> 385 </trkpt> 386 <trkpt lat="47.1974522061646" lon="8.791516218334436"> 387 <ele>482.81</ele> 388 <time>2016-01-03T12:05:11.000Z</time> 389 </trkpt> 390 <trkpt lat="47.197455475106835" lon="8.79138101823628"> 391 <ele>481.99000000000001</ele> 392 <time>2016-01-03T12:05:12.000Z</time> 393 </trkpt> 394 <trkpt lat="47.197490092366934" lon="8.79095789976418"> 395 <ele>478.92</ele> 396 </trkpt> 397 <trkpt lat="47.19753225333989" lon="8.790533943101764"> 398 <ele>476</ele> 399 </trkpt> 400 <trkpt lat="47.19762864522636" lon="8.789889458566904"> 401 <ele>474.38</ele> 402 <time>2016-01-03T12:05:23.000Z</time> 403 </trkpt> 404 <trkpt lat="47.19763744622469" lon="8.789792899042368"> 405 <ele>474.35000000000002</ele> 406 <time>2016-01-03T12:05:24.000Z</time> 407 </trkpt> 408 <trkpt lat="47.1976438164711" lon="8.789720982313156"> 409 <ele>474.12</ele> 410 <time>2016-01-03T12:05:25.000Z</time> 411 </trkpt> 412 <trkpt lat="47.19764859415591" lon="8.789367768913507"> 413 <ele>472.52999999999997</ele> 414 <time>2016-01-03T12:05:33.000Z</time> 415 </trkpt> 416 <trkpt lat="47.19765613786876" lon="8.78931068815291"> 417 <ele>472.75</ele> 418 <time>2016-01-03T12:05:34.000Z</time> 419 </trkpt> 420 <trkpt lat="47.1976903360337" lon="8.789105415344238"> 421 <ele>472.19</ele> 422 <time>2016-01-03T12:05:37.000Z</time> 423 </trkpt> 424 <trkpt lat="47.197700729593635" lon="8.78903266042471"> 425 <ele>471.92000000000002</ele> 426 <time>2016-01-03T12:05:38.000Z</time> 427 </trkpt> 428 <trkpt lat="47.197715900838375" lon="8.78876687027514"> 429 <ele>471.98000000000002</ele> 430 <time>2016-01-03T12:05:41.000Z</time> 431 </trkpt> 432 <trkpt lat="47.19775462523103" lon="8.788432851433754"> 433 <ele>473.49000000000001</ele> 434 <time>2016-01-03T12:05:47.000Z</time> 435 </trkpt> 436 <trkpt lat="47.197777507826686" lon="8.78841600380838"> 437 <ele>473.44999999999999</ele> 438 <time>2016-01-03T12:05:48.000Z</time> 439 </trkpt> 440 <trkpt lat="47.19780064187944" lon="8.788405358791351"> 441 <ele>473.45999999999998</ele> 442 <time>2016-01-03T12:05:49.000Z</time> 443 </trkpt> 444 <trkpt lat="47.197963669896126" lon="8.788386499509215"> 445 <ele>470.27999999999997</ele> 446 <time>2016-01-03T12:05:53.000Z</time> 447 </trkpt> 448 <trkpt lat="47.1981308888644" lon="8.788295891135931"> 449 <ele>467.20999999999998</ele> 450 <time>2016-01-03T12:05:57.000Z</time> 451 </trkpt> 452 <trkpt lat="47.19813633710146" lon="8.788262866437435"> 453 <ele>466.89999999999998</ele> 454 <time>2016-01-03T12:05:58.000Z</time> 455 </trkpt> 456 <trkpt lat="47.19812661409378" lon="8.788229255005717"> 457 <ele>466.76999999999998</ele> 458 <time>2016-01-03T12:05:59.000Z</time> 459 </trkpt> 460 <trkpt lat="47.19810306094587" lon="8.788186172023416"> 461 <ele>466.25</ele> 462 <time>2016-01-03T12:06:00.000Z</time> 463 </trkpt> 464 <trkpt lat="47.19808369874954" lon="8.788127414882183"> 465 <ele>465.23000000000002</ele> 466 <time>2016-01-03T12:06:01.000Z</time> 467 </trkpt> 468 <trkpt lat="47.19807816669345" lon="8.788059940561652"> 469 <ele>464.12</ele> 470 <time>2016-01-03T12:06:02.000Z</time> 471 </trkpt> 472 <trkpt lat="47.19808881171048" lon="8.787991376593709"> 473 <ele>463.68000000000001</ele> 474 <time>2016-01-03T12:06:03.000Z</time> 475 </trkpt> 476 <trkpt lat="47.19811093993485" lon="8.787914346903563"> 477 <ele>462.5</ele> 478 <time>2016-01-03T12:06:04.000Z</time> 479 </trkpt> 480 <trkpt lat="47.19815100543201" lon="8.78783798776567"> 481 <ele>462.45999999999998</ele> 482 <time>2016-01-03T12:06:05.000Z</time> 483 </trkpt> 484 <trkpt lat="47.19819492660463" lon="8.787756934762001"> 485 <ele>461.56999999999999</ele> 486 <time>2016-01-03T12:06:06.000Z</time> 487 </trkpt> 488 <trkpt lat="47.1982860378921" lon="8.787589464336634"> 489 <ele>461.14999999999998</ele> 490 <time>2016-01-03T12:06:08.000Z</time> 491 </trkpt> 492 <trkpt lat="47.19831814058125" lon="8.7874944973737"> 493 <ele>460.19</ele> 494 <time>2016-01-03T12:06:09.000Z</time> 495 </trkpt> 496 <trkpt lat="47.1983309648931" lon="8.787389053031802"> 497 <ele>459.83999999999997</ele> 498 <time>2016-01-03T12:06:10.000Z</time> 499 </trkpt> 500 <trkpt lat="47.198331551626325" lon="8.787284530699253"> 501 <ele>460.49000000000001</ele> 502 <time>2016-01-03T12:06:11.000Z</time> 503 </trkpt> 504 <trkpt lat="47.198325265198946" lon="8.787185624241829"> 505 <ele>460.23000000000002</ele> 506 <time>2016-01-03T12:06:12.000Z</time> 507 </trkpt> 508 <trkpt lat="47.19824245199561" lon="8.78635254688561"> 509 <ele>460.56999999999999</ele> 510 <time>2016-01-03T12:06:22.000Z</time> 511 </trkpt> 512 <trkpt lat="47.198192747309804" lon="8.78586145117879"> 513 <ele>457.79000000000002</ele> 514 <time>2016-01-03T12:06:27.000Z</time> 515 </trkpt> 516 <trkpt lat="47.19819249585271" lon="8.78536943346262"> 517 <ele>454.66000000000003</ele> 518 <time>2016-01-03T12:06:31.000Z</time> 519 </trkpt> 520 </trkseg> 521 </trk> 522 <trk> 523 <trkseg> 524 <trkpt lat="47.18660652637482" lon="8.796921372413635"> 525 <ele>624.7421875</ele> 526 </trkpt> 527 <trkpt lat="47.186644077301025" lon="8.7968248128891"> 528 <ele>626.015625</ele> 529 </trkpt> 530 <trkpt lat="47.18669772148132" lon="8.796712160110474"> 531 <ele>627.0625</ele> 532 </trkpt> 533 <trkpt lat="47.18676209449768" lon="8.796610236167908"> 534 <ele>627.3671875</ele> 535 </trkpt> 536 <trkpt lat="47.1868371963501" lon="8.796519041061401"> 537 <ele>626.90234375</ele> 538 </trkpt> 539 <trkpt lat="47.186912298202515" lon="8.796401023864746"> 540 <ele>626.11328125</ele> 541 </trkpt> 542 <trkpt lat="47.18698740005493" lon="8.796277642250061"> 543 <ele>625.33203125</ele> 544 </trkpt> 545 <trkpt lat="47.18707859516144" lon="8.796148896217346"> 546 <ele>623.90625</ele> 547 </trkpt> 548 <trkpt lat="47.18710541725159" lon="8.796095252037048"> 549 <ele>623.66796875</ele> 550 </trkpt> 551 <trkpt lat="47.187126874923706" lon="8.796030879020691"> 552 <ele>623.71484375</ele> 553 </trkpt> 554 <trkpt lat="47.187132239341736" lon="8.795977234840393"> 555 <ele>623.75</ele> 556 </trkpt> 557 <trkpt lat="47.187132239341736" lon="8.795923590660095"> 558 <ele>623.9375</ele> 559 </trkpt> 560 <trkpt lat="47.187132239341736" lon="8.795859217643738"> 561 <ele>624.1640625</ele> 562 </trkpt> 563 <trkpt lat="47.18711078166962" lon="8.795735836029053"> 564 <ele>625.234375</ele> 565 </trkpt> 566 <trkpt lat="47.18710005283356" lon="8.795607089996338"> 567 <ele>626</ele> 568 </trkpt> 569 <trkpt lat="47.18709468841553" lon="8.795521259307861"> 570 <ele>626.3515625</ele> 571 </trkpt> 572 <trkpt lat="47.18710541725159" lon="8.795440793037415"> 573 <ele>626.14453125</ele> 574 </trkpt> 575 <trkpt lat="47.187126874923706" lon="8.795360326766968"> 576 <ele>625.6640625</ele> 577 </trkpt> 578 <trkpt lat="47.187164425849915" lon="8.79528522491455"> 579 <ele>624.7890625</ele> 580 </trkpt> 581 <trkpt lat="47.1872341632843" lon="8.795183300971985"> 582 <ele>623.23046875</ele> 583 </trkpt> 584 <trkpt lat="47.18729317188263" lon="8.795086741447449"> 585 <ele>622.09375</ele> 586 </trkpt> 587 <trkpt lat="47.18736290931702" lon="8.794984817504883"> 588 <ele>620.9765625</ele> 589 </trkpt> 590 <trkpt lat="47.187416553497314" lon="8.794904351234436"> 591 <ele>620.23828125</ele> 592 </trkpt> 593 <trkpt lat="47.18746483325958" lon="8.794845342636108"> 594 <ele>619.42578125</ele> 595 </trkpt> 596 <trkpt lat="47.18752384185791" lon="8.79479706287384"> 597 <ele>617.7734375</ele> 598 </trkpt> 599 <trkpt lat="47.18756139278412" lon="8.794743418693542"> 600 <ele>616.8671875</ele> 601 </trkpt> 602 <trkpt lat="47.1875935792923" lon="8.794695138931274"> 603 <ele>616.09765625</ele> 604 </trkpt> 605 <trkpt lat="47.18760967254639" lon="8.794630765914917"> 606 <ele>615.87890625</ele> 607 </trkpt> 608 <trkpt lat="47.187620401382446" lon="8.7945556640625"> 609 <ele>615.3984375</ele> 610 </trkpt> 611 <trkpt lat="47.187636494636536" lon="8.794485926628113"> 612 <ele>614.76953125</ele> 613 </trkpt> 614 <trkpt lat="47.187674045562744" lon="8.794400095939636"> 615 <ele>613.47265625</ele> 616 </trkpt> 617 <trkpt lat="47.18769550323486" lon="8.79430890083313"> 618 <ele>612.72265625</ele> 619 </trkpt> 620 <trkpt lat="47.18770086765289" lon="8.794185519218445"> 621 <ele>612.4609375</ele> 622 </trkpt> 623 <trkpt lat="47.18770086765289" lon="8.79407823085785"> 624 <ele>611.85546875</ele> 625 </trkpt> 626 <trkpt lat="47.187684774398804" lon="8.793997764587402"> 627 <ele>611.90625</ele> 628 </trkpt> 629 <trkpt lat="47.187663316726685" lon="8.793933391571045"> 630 <ele>612.27734375</ele> 631 </trkpt> 632 <trkpt lat="47.18761503696442" lon="8.793869018554688"> 633 <ele>613.66796875</ele> 634 </trkpt> 635 <trkpt lat="47.18758285045624" lon="8.79381537437439"> 636 <ele>614.62890625</ele> 637 </trkpt> 638 <trkpt lat="47.18756675720215" lon="8.793767094612122"> 639 <ele>615.0703125</ele> 640 </trkpt> 641 <trkpt lat="47.18757212162018" lon="8.793713450431824"> 642 <ele>614.72265625</ele> 643 </trkpt> 644 <trkpt lat="47.18758821487427" lon="8.793681263923645"> 645 <ele>614.26171875</ele> 646 </trkpt> 647 <trkpt lat="47.187641859054565" lon="8.793681263923645"> 648 <ele>612.06640625</ele> 649 </trkpt> 650 <trkpt lat="47.18770086765289" lon="8.793708086013794"> 651 <ele>609.6875</ele> 652 </trkpt> 653 <trkpt lat="47.18778133392334" lon="8.793751001358032"> 654 <ele>606.83984375</ele> 655 </trkpt> 656 <trkpt lat="47.18785107135773" lon="8.79380464553833"> 657 <ele>604.671875</ele> 658 </trkpt> 659 <trkpt lat="47.187920808792114" lon="8.793842196464539"> 660 <ele>602.52734375</ele> 661 </trkpt> 662 <trkpt lat="47.18800127506256" lon="8.793911933898926"> 663 <ele>600.78515625</ele> 664 </trkpt> 665 <trkpt lat="47.18811392784119" lon="8.794013857841492"> 666 <ele>598.078125</ele> 667 </trkpt> 668 <trkpt lat="47.188151478767395" lon="8.79406213760376"> 669 <ele>597.1953125</ele> 670 </trkpt> 671 <trkpt lat="47.1881890296936" lon="8.794153332710266"> 672 <ele>596.5234375</ele> 673 </trkpt> 674 <trkpt lat="47.18821585178375" lon="8.794239163398743"> 675 <ele>595.74609375</ele> 676 </trkpt> 677 <trkpt lat="47.1882426738739" lon="8.794351816177368"> 678 <ele>594.82421875</ele> 679 </trkpt> 680 <trkpt lat="47.18826413154602" lon="8.794426918029785"> 681 <ele>594.10546875</ele> 682 </trkpt> 683 <trkpt lat="47.18829095363617" lon="8.794475197792053"> 684 <ele>593.2109375</ele> 685 </trkpt> 686 <trkpt lat="47.18830704689026" lon="8.794523477554321"> 687 <ele>592.6875</ele> 688 </trkpt> 689 <trkpt lat="47.18831241130829" lon="8.794614672660828"> 690 <ele>592.5390625</ele> 691 </trkpt> 692 <trkpt lat="47.18830704689026" lon="8.79479706287384"> 693 <ele>592.7578125</ele> 694 </trkpt> 695 <trkpt lat="47.18830704689026" lon="8.794888257980347"> 696 <ele>592.77734375</ele> 697 </trkpt> 698 <trkpt lat="47.18831241130829" lon="8.794941902160645"> 699 <ele>592.63671875</ele> 700 </trkpt> 701 <trkpt lat="47.18833386898041" lon="8.794995546340942"> 702 <ele>592.06640625</ele> 703 </trkpt> 704 <trkpt lat="47.188366055488586" lon="8.7950599193573"> 705 <ele>591.2578125</ele> 706 </trkpt> 707 <trkpt lat="47.188403606414795" lon="8.795113563537598"> 708 <ele>590.46875</ele> 709 </trkpt> 710 <trkpt lat="47.188435792922974" lon="8.795167207717896"> 711 <ele>589.7578125</ele> 712 </trkpt> 713 <trkpt lat="47.18845188617706" lon="8.795226216316223"> 714 <ele>589.359375</ele> 715 </trkpt> 716 <trkpt lat="47.18846261501312" lon="8.79529058933258"> 717 <ele>589.05859375</ele> 718 </trkpt> 719 <trkpt lat="47.18845188617706" lon="8.795354962348938"> 720 <ele>589.21875</ele> 721 </trkpt> 722 <trkpt lat="47.188430428504944" lon="8.795451521873474"> 723 <ele>589.59375</ele> 724 </trkpt> 725 <trkpt lat="47.188408970832825" lon="8.7955641746521"> 726 <ele>589.98046875</ele> 727 </trkpt> 728 <trkpt lat="47.188403606414795" lon="8.795655369758606"> 729 <ele>589.51953125</ele> 730 </trkpt> 731 <trkpt lat="47.188408970832825" lon="8.795746564865112"> 732 <ele>588.796875</ele> 733 </trkpt> 734 <trkpt lat="47.188435792922974" lon="8.795859217643738"> 735 <ele>587.4375</ele> 736 </trkpt> 737 <trkpt lat="47.18847870826721" lon="8.795971870422363"> 738 <ele>585.70703125</ele> 739 </trkpt> 740 <trkpt lat="47.18850553035736" lon="8.79605233669281"> 741 <ele>584.48046875</ele> 742 </trkpt> 743 <trkpt lat="47.18852162361145" lon="8.796132802963257"> 744 <ele>583.328125</ele> 745 </trkpt> 746 <trkpt lat="47.18852162361145" lon="8.796197175979614"> 747 <ele>582.69921875</ele> 748 </trkpt> 749 <trkpt lat="47.18851625919342" lon="8.79628300666809"> 750 <ele>581.96875</ele> 751 </trkpt> 752 <trkpt lat="47.18850016593933" lon="8.796379566192627"> 753 <ele>581.3359375</ele> 754 </trkpt> 755 <trkpt lat="47.18848943710327" lon="8.796465396881104"> 756 <ele>580.6796875</ele> 757 </trkpt> 758 <trkpt lat="47.18848943710327" lon="8.796524405479431"> 759 <ele>580.33984375</ele> 760 </trkpt> 761 <trkpt lat="47.18850016593933" lon="8.796578049659729"> 762 <ele>580.0234375</ele> 763 </trkpt> 764 <trkpt lat="47.18852162361145" lon="8.796631693840027"> 765 <ele>579.5078125</ele> 766 </trkpt> 767 <trkpt lat="47.1885484457016" lon="8.796685338020325"> 768 <ele>578.890625</ele> 769 </trkpt> 770 <trkpt lat="47.18856990337372" lon="8.796749711036682"> 771 <ele>578.34375</ele> 772 </trkpt> 773 <trkpt lat="47.18858063220978" lon="8.79681944847107"> 774 <ele>577.984375</ele> 775 </trkpt> 776 <trkpt lat="47.18857526779175" lon="8.796899914741516"> 777 <ele>577.90234375</ele> 778 </trkpt> 779 <trkpt lat="47.18858599662781" lon="8.796991109848022"> 780 <ele>577.50390625</ele> 781 </trkpt> 782 <trkpt lat="47.18859672546387" lon="8.79704475402832"> 783 <ele>577.20703125</ele> 784 </trkpt> 785 <trkpt lat="47.188623547554016" lon="8.797119855880737"> 786 <ele>576.6171875</ele> 787 </trkpt> 788 <trkpt lat="47.188666462898254" lon="8.797189593315125"> 789 <ele>575.82421875</ele> 790 </trkpt> 791 <trkpt lat="47.18870937824249" lon="8.797211050987244"> 792 <ele>575.125</ele> 793 </trkpt> 794 <trkpt lat="47.18871474266052" lon="8.797157406806946"> 795 <ele>575.0546875</ele> 796 </trkpt> 797 <trkpt lat="47.18872547149658" lon="8.79705548286438"> 798 <ele>574.89453125</ele> 799 </trkpt> 800 <trkpt lat="47.18873620033264" lon="8.796937465667725"> 801 <ele>574.75</ele> 802 </trkpt> 803 <trkpt lat="47.18875765800476" lon="8.79681408405304"> 804 <ele>574.6484375</ele> 805 </trkpt> 806 <trkpt lat="47.18879520893097" lon="8.796685338020325"> 807 <ele>574.26953125</ele> 808 </trkpt> 809 <trkpt lat="47.18883812427521" lon="8.796588778495789"> 810 <ele>573.72265625</ele> 811 </trkpt> 812 <trkpt lat="47.188907861709595" lon="8.796438574790955"> 813 <ele>572.4296875</ele> 814 </trkpt> 815 <trkpt lat="47.18901515007019" lon="8.796240091323853"> 816 <ele>570.828125</ele> 817 </trkpt> 818 <trkpt lat="47.18906342983246" lon="8.796154260635376"> 819 <ele>570.1015625</ele> 820 </trkpt> 821 <trkpt lat="47.189154624938965" lon="8.795987963676453"> 822 <ele>568.7734375</ele> 823 </trkpt> 824 <trkpt lat="47.18921899795532" lon="8.795869946479797"> 825 <ele>567.8125</ele> 826 </trkpt> 827 <trkpt lat="47.18926191329956" lon="8.795778751373291"> 828 <ele>567.25390625</ele> 829 </trkpt> 830 <trkpt lat="47.18928337097168" lon="8.795714378356934"> 831 <ele>567.09765625</ele> 832 </trkpt> 833 <trkpt lat="47.18929409980774" lon="8.795660734176636"> 834 <ele>567.1640625</ele> 835 </trkpt> 836 <trkpt lat="47.18929946422577" lon="8.795580267906189"> 837 <ele>567.546875</ele> 838 </trkpt> 839 <trkpt lat="47.18929946422577" lon="8.795451521873474"> 840 <ele>567.86328125</ele> 841 </trkpt> 842 <trkpt lat="47.18929409980774" lon="8.7953120470047"> 843 <ele>568.2890625</ele> 844 </trkpt> 845 <trkpt lat="47.18929409980774" lon="8.795210123062134"> 846 <ele>568.49609375</ele> 847 </trkpt> 848 <trkpt lat="47.1893048286438" lon="8.795135021209717"> 849 <ele>568.33203125</ele> 850 </trkpt> 851 <trkpt lat="47.18934237957001" lon="8.794904351234436"> 852 <ele>566.84765625</ele> 853 </trkpt> 854 <trkpt lat="47.18934774398804" lon="8.794845342636108"> 855 <ele>566.609375</ele> 856 </trkpt> 857 <trkpt lat="47.18933701515198" lon="8.794738054275513"> 858 <ele>566.94140625</ele> 859 </trkpt> 860 <trkpt lat="47.18933701515198" lon="8.794657588005066"> 861 <ele>566.88671875</ele> 862 </trkpt> 863 <trkpt lat="47.18935310840607" lon="8.79457712173462"> 864 <ele>566.27734375</ele> 865 </trkpt> 866 <trkpt lat="47.189374566078186" lon="8.794502019882202"> 867 <ele>565.48046875</ele> 868 </trkpt> 869 <trkpt lat="47.189428210258484" lon="8.794384002685547"> 870 <ele>563.5</ele> 871 </trkpt> 872 <trkpt lat="47.18945503234863" lon="8.7943035364151"> 873 <ele>562.51953125</ele> 874 </trkpt> 875 <trkpt lat="47.18947112560272" lon="8.794206976890564"> 876 <ele>561.9453125</ele> 877 </trkpt> 878 <trkpt lat="47.18948185443878" lon="8.79407286643982"> 879 <ele>561.85546875</ele> 880 </trkpt> 881 <trkpt lat="47.18949794769287" lon="8.793911933898926"> 882 <ele>561.7578125</ele> 883 </trkpt> 884 <trkpt lat="47.18950867652893" lon="8.79378855228424"> 885 <ele>561.765625</ele> 886 </trkpt> 887 <trkpt lat="47.18952476978302" lon="8.793686628341675"> 888 <ele>561.453125</ele> 889 </trkpt> 890 <trkpt lat="47.18955159187317" lon="8.79356861114502"> 891 <ele>560.6015625</ele> 892 </trkpt> 893 <trkpt lat="47.18958377838135" lon="8.793466687202454"> 894 <ele>559.65234375</ele> 895 </trkpt> 896 <trkpt lat="47.189615964889526" lon="8.793386220932007"> 897 <ele>558.7578125</ele> 898 </trkpt> 899 <trkpt lat="47.189658880233765" lon="8.793278932571411"> 900 <ele>557.66015625</ele> 901 </trkpt> 902 <trkpt lat="47.18971252441406" lon="8.793187737464905"> 903 <ele>556.35546875</ele> 904 </trkpt> 905 <trkpt lat="47.18976080417633" lon="8.793118000030518"> 906 <ele>555.2265625</ele> 907 </trkpt> 908 <trkpt lat="47.18983054161072" lon="8.79304826259613"> 909 <ele>553.53125</ele> 910 </trkpt> 911 <trkpt lat="47.189921736717224" lon="8.792962431907654"> 912 <ele>551.265625</ele> 913 </trkpt> 914 <trkpt lat="47.18997538089752" lon="8.792903423309326"> 915 <ele>549.92578125</ele> 916 </trkpt> 917 <trkpt lat="47.1900075674057" lon="8.792855143547058"> 918 <ele>549.140625</ele> 919 </trkpt> 920 <trkpt lat="47.19003438949585" lon="8.792780041694641"> 921 <ele>548.48828125</ele> 922 </trkpt> 923 <trkpt lat="47.19004511833191" lon="8.792726397514343"> 924 <ele>548.0078125</ele> 925 </trkpt> 926 <trkpt lat="47.19005584716797" lon="8.792635202407837"> 927 <ele>547.39453125</ele> 928 </trkpt> 929 <trkpt lat="47.19005584716797" lon="8.79256546497345"> 930 <ele>547.15234375</ele> 931 </trkpt> 932 <trkpt lat="47.19005048274994" lon="8.792501091957092"> 933 <ele>547.08203125</ele> 934 </trkpt> 935 <trkpt lat="47.19001829624176" lon="8.792366981506348"> 936 <ele>547.55078125</ele> 937 </trkpt> 938 <trkpt lat="47.18994319438934" lon="8.792104125022888"> 939 <ele>548.69921875</ele> 940 </trkpt> 941 <trkpt lat="47.189932465553284" lon="8.792034387588501"> 942 <ele>548.76953125</ele> 943 </trkpt> 944 <trkpt lat="47.189932465553284" lon="8.791970014572144"> 945 <ele>548.51953125</ele> 946 </trkpt> 947 <trkpt lat="47.18994319438934" lon="8.791900277137756"> 948 <ele>547.88671875</ele> 949 </trkpt> 950 <trkpt lat="47.18997001647949" lon="8.79183053970337"> 951 <ele>546.7265625</ele> 952 </trkpt> 953 <trkpt lat="47.19000220298767" lon="8.791755437850952"> 954 <ele>545.3984375</ele> 955 </trkpt> 956 <trkpt lat="47.19003975391388" lon="8.791680335998535"> 957 <ele>543.87890625</ele> 958 </trkpt> 959 <trkpt lat="47.190120220184326" lon="8.791535496711731"> 960 <ele>540.6484375</ele> 961 </trkpt> 962 <trkpt lat="47.19023287296295" lon="8.79129409790039"> 963 <ele>536.4296875</ele> 964 </trkpt> 965 <trkpt lat="47.19025433063507" lon="8.791224360466003"> 966 <ele>536.046875</ele> 967 </trkpt> 968 <trkpt lat="47.19027042388916" lon="8.791149258613586"> 969 <ele>535.765625</ele> 970 </trkpt> 971 <trkpt lat="47.19027578830719" lon="8.791015148162842"> 972 <ele>535.71875</ele> 973 </trkpt> 974 <trkpt lat="47.19027578830719" lon="8.790768384933472"> 975 <ele>535.55859375</ele> 976 </trkpt> 977 <trkpt lat="47.19026505947113" lon="8.790435791015625"> 978 <ele>535.359375</ele> 979 </trkpt> 980 <trkpt lat="47.1902596950531" lon="8.790162205696106"> 981 <ele>534.5234375</ele> 982 </trkpt> 983 <trkpt lat="47.1902596950531" lon="8.789920806884766"> 984 <ele>534.2578125</ele> 985 </trkpt> 986 <trkpt lat="47.19025433063507" lon="8.789674043655396"> 987 <ele>535.1328125</ele> 988 </trkpt> 989 <trkpt lat="47.19025433063507" lon="8.78955602645874"> 990 <ele>535.46875</ele> 991 </trkpt> 992 <trkpt lat="47.19025433063507" lon="8.789491653442383"> 993 <ele>535.04296875</ele> 994 </trkpt> 995 <trkpt lat="47.19027042388916" lon="8.789438009262085"> 996 <ele>534.04296875</ele> 997 </trkpt> 998 <trkpt lat="47.19030797481537" lon="8.789384365081787"> 999 <ele>532.234375</ele> 1000 </trkpt> 1001 <trkpt lat="47.19035625457764" lon="8.789357542991638"> 1002 <ele>530.2109375</ele> 1003 </trkpt> 1004 <trkpt lat="47.190393805503845" lon="8.789357542991638"> 1005 <ele>528.7890625</ele> 1006 </trkpt> 1007 <trkpt lat="47.190425992012024" lon="8.789373636245728"> 1008 <ele>527.69140625</ele> 1009 </trkpt> 1010 <trkpt lat="47.1904581785202" lon="8.789411187171936"> 1011 <ele>526.76171875</ele> 1012 </trkpt> 1013 <trkpt lat="47.19048500061035" lon="8.789459466934204"> 1014 <ele>526.1171875</ele> 1015 </trkpt> 1016 <trkpt lat="47.19050645828247" lon="8.789529204368591"> 1017 <ele>525.83984375</ele> 1018 </trkpt> 1019 <trkpt lat="47.19052255153656" lon="8.789609670639038"> 1020 <ele>525.51171875</ele> 1021 </trkpt> 1022 <trkpt lat="47.19053328037262" lon="8.789727687835693"> 1023 <ele>525.34375</ele> 1024 </trkpt> 1025 <trkpt lat="47.19054400920868" lon="8.78982961177826"> 1026 <ele>525.18359375</ele> 1027 </trkpt> 1028 <trkpt lat="47.19058692455292" lon="8.790022730827332"> 1029 <ele>524.3515625</ele> 1030 </trkpt> 1031 <trkpt lat="47.190635204315186" lon="8.790242671966553"> 1032 <ele>524.41015625</ele> 1033 </trkpt> 1034 <trkpt lat="47.190672755241394" lon="8.790398240089417"> 1035 <ele>524.47265625</ele> 1036 </trkpt> 1037 <trkpt lat="47.19072639942169" lon="8.79054844379425"> 1038 <ele>524.02734375</ele> 1039 </trkpt> 1040 <trkpt lat="47.19078004360199" lon="8.790677189826965"> 1041 <ele>523.09375</ele> 1042 </trkpt> 1043 <trkpt lat="47.19083368778229" lon="8.79082202911377"> 1044 <ele>521.92578125</ele> 1045 </trkpt> 1046 <trkpt lat="47.190876603126526" lon="8.790961503982544"> 1047 <ele>520.87109375</ele> 1048 </trkpt> 1049 <trkpt lat="47.190908789634705" lon="8.791095614433289"> 1050 <ele>520.51953125</ele> 1051 </trkpt> 1052 <trkpt lat="47.19093561172485" lon="8.791192173957825"> 1053 <ele>520.2578125</ele> 1054 </trkpt> 1055 <trkpt lat="47.19097316265106" lon="8.791267275810242"> 1056 <ele>519.6640625</ele> 1057 </trkpt> 1058 <trkpt lat="47.19103217124939" lon="8.791337013244629"> 1059 <ele>518.5703125</ele> 1060 </trkpt> 1061 <trkpt lat="47.191112637519836" lon="8.791401386260986"> 1062 <ele>517.04296875</ele> 1063 </trkpt> 1064 <trkpt lat="47.19128429889679" lon="8.791524767875671"> 1065 <ele>513.03125</ele> 1066 </trkpt> 1067 <trkpt lat="47.191407680511475" lon="8.791610598564148"> 1068 <ele>510.19921875</ele> 1069 </trkpt> 1070 <trkpt lat="47.19148814678192" lon="8.791669607162476"> 1071 <ele>508.5</ele> 1072 </trkpt> 1073 <trkpt lat="47.1915203332901" lon="8.791696429252625"> 1074 <ele>507.8828125</ele> 1075 </trkpt> 1076 <trkpt lat="47.19157934188843" lon="8.791739344596863"> 1077 <ele>506.71875</ele> 1078 </trkpt> 1079 <trkpt lat="47.191627621650696" lon="8.79179835319519"> 1080 <ele>506.03125</ele> 1081 </trkpt> 1082 <trkpt lat="47.191659808158875" lon="8.791851997375488"> 1083 <ele>505.5390625</ele> 1084 </trkpt> 1085 <trkpt lat="47.19168663024902" lon="8.791916370391846"> 1086 <ele>504.96875</ele> 1087 </trkpt> 1088 <trkpt lat="47.1917188167572" lon="8.792018294334412"> 1089 <ele>504.28125</ele> 1090 </trkpt> 1091 <trkpt lat="47.19175100326538" lon="8.792141675949097"> 1092 <ele>503.6640625</ele> 1093 </trkpt> 1094 <trkpt lat="47.19179928302765" lon="8.79229724407196"> 1095 <ele>502.578125</ele> 1096 </trkpt> 1097 <trkpt lat="47.19184219837189" lon="8.792458176612854"> 1098 <ele>500.921875</ele> 1099 </trkpt> 1100 <trkpt lat="47.191869020462036" lon="8.79257082939148"> 1101 <ele>499.85546875</ele> 1102 </trkpt> 1103 <trkpt lat="47.191879749298096" lon="8.792662024497986"> 1104 <ele>499.40234375</ele> 1105 </trkpt> 1106 <trkpt lat="47.191890478134155" lon="8.792763948440552"> 1107 <ele>498.96875</ele> 1108 </trkpt> 1109 <trkpt lat="47.191895842552185" lon="8.792887330055237"> 1110 <ele>497.8828125</ele> 1111 </trkpt> 1112 <trkpt lat="47.191895842552185" lon="8.79306435585022"> 1113 <ele>496.2265625</ele> 1114 </trkpt> 1115 <trkpt lat="47.191901206970215" lon="8.793182373046875"> 1116 <ele>494.9609375</ele> 1117 </trkpt> 1118 <trkpt lat="47.191906571388245" lon="8.793257474899292"> 1119 <ele>494.13671875</ele> 1120 </trkpt> 1121 <trkpt lat="47.191928029060364" lon="8.793343305587769"> 1122 <ele>493.6015625</ele> 1123 </trkpt> 1124 <trkpt lat="47.19196021556854" lon="8.793472051620483"> 1125 <ele>492.828125</ele> 1126 </trkpt> 1127 <trkpt lat="47.19199282117188" lon="8.793616723269224"> 1128 <ele>492.1015625</ele> 1129 </trkpt> 1130 <trkpt lat="47.19200849533081" lon="8.793686628341675"> 1131 <ele>491.76953125</ele> 1132 </trkpt> 1133 <trkpt lat="47.19204068183899" lon="8.793852925300598"> 1134 <ele>490.83984375</ele> 1135 </trkpt> 1136 <trkpt lat="47.19206213951111" lon="8.793992400169373"> 1137 <ele>490.23828125</ele> 1138 </trkpt> 1139 <trkpt lat="47.19207286834717" lon="8.7940514087677"> 1140 <ele>489.96484375</ele> 1141 </trkpt> 1142 <trkpt lat="47.19208359718323" lon="8.794147968292236"> 1143 <ele>489.703125</ele> 1144 </trkpt> 1145 <trkpt lat="47.192121148109436" lon="8.795000910758972"> 1146 <ele>484.7109375</ele> 1147 </trkpt> 1148 <trkpt lat="47.192137241363525" lon="8.79530131816864"> 1149 <ele>482.328125</ele> 1150 </trkpt> 1151 <trkpt lat="47.192137241363525" lon="8.795451521873474"> 1152 <ele>481.04296875</ele> 1153 </trkpt> 1154 <trkpt lat="47.192137241363525" lon="8.79553735256195"> 1155 <ele>480.3046875</ele> 1156 </trkpt> 1157 <trkpt lat="47.192126512527466" lon="8.795607089996338"> 1158 <ele>479.70703125</ele> 1159 </trkpt> 1160 <trkpt lat="47.19211041927338" lon="8.795682191848755"> 1161 <ele>478.984375</ele> 1162 </trkpt> 1163 <trkpt lat="47.19208896160126" lon="8.795746564865112"> 1164 <ele>478.4609375</ele> 1165 </trkpt> 1166 <trkpt lat="47.19203531742096" lon="8.795832395553589"> 1167 <ele>479.1015625</ele> 1168 </trkpt> 1169 <trkpt lat="47.19198167324066" lon="8.795896768569946"> 1170 <ele>480.359375</ele> 1171 </trkpt> 1172 <trkpt lat="47.19194948673248" lon="8.795934319496155"> 1173 <ele>481.19140625</ele> 1174 </trkpt> 1175 <trkpt lat="47.191906571388245" lon="8.795993328094482"> 1176 <ele>482.2890625</ele> 1177 </trkpt> 1178 <trkpt lat="47.191869020462036" lon="8.79606306552887"> 1179 <ele>483.28125</ele> 1180 </trkpt> 1181 <trkpt lat="47.19184756278992" lon="8.796138167381287"> 1182 <ele>483.69921875</ele> 1183 </trkpt> 1184 <trkpt lat="47.19184219837189" lon="8.796213269233704"> 1185 <ele>483.4609375</ele> 1186 </trkpt> 1187 <trkpt lat="47.19184219837189" lon="8.79628300666809"> 1188 <ele>483.0390625</ele> 1189 </trkpt> 1190 <trkpt lat="47.19185829162598" lon="8.796374201774597"> 1191 <ele>481.9140625</ele> 1192 </trkpt> 1193 <trkpt lat="47.191885113716125" lon="8.796454668045044"> 1194 <ele>480.515625</ele> 1195 </trkpt> 1196 <trkpt lat="47.191917300224304" lon="8.796513676643372"> 1197 <ele>479.16796875</ele> 1198 </trkpt> 1199 <trkpt lat="47.19198703765869" lon="8.796631693840027"> 1200 <ele>476.74609375</ele> 1201 </trkpt> 1202 <trkpt lat="47.19206750392914" lon="8.796760439872742"> 1203 <ele>474.3515625</ele> 1204 </trkpt> 1205 <trkpt lat="47.192131876945496" lon="8.796835541725159"> 1206 <ele>473.28515625</ele> 1207 </trkpt> 1208 <trkpt lat="47.19219088554382" lon="8.796894550323486"> 1209 <ele>472.39453125</ele> 1210 </trkpt> 1211 <trkpt lat="47.19225525856018" lon="8.796948194503784"> 1212 <ele>471.3671875</ele> 1213 </trkpt> 1214 <trkpt lat="47.19234645366669" lon="8.797001838684082"> 1215 <ele>470.0390625</ele> 1216 </trkpt> 1217 <trkpt lat="47.192426919937134" lon="8.79704475402832"> 1218 <ele>468.76171875</ele> 1219 </trkpt> 1220 <trkpt lat="47.19250738620758" lon="8.797082304954529"> 1221 <ele>467.3671875</ele> 1222 </trkpt> 1223 <trkpt lat="47.19255566596985" lon="8.797114491462708"> 1224 <ele>466.60546875</ele> 1225 </trkpt> 1226 <trkpt lat="47.1927273273468" lon="8.797253966331482"> 1227 <ele>464.65625</ele> 1228 </trkpt> 1229 <trkpt lat="47.19280779361725" lon="8.79730761051178"> 1230 <ele>463.62109375</ele> 1231 </trkpt> 1232 <trkpt lat="47.19286604784429" lon="8.79733837209642"> 1233 <ele>462.84375</ele> 1234 </trkpt> 1235 <trkpt lat="47.19286596402526" lon="8.797338204458356"> 1236 <ele>462.84765625</ele> 1237 </trkpt> 1238 </trkseg> 1239 </trk> 1240 <trk> 1241 <trkseg> 1242 <trkpt lat="47.18561486341059" lon="8.796475538983941"> 1243 <ele>647.81640625</ele> 1244 </trkpt> 1245 <trkpt lat="47.185668759047985" lon="8.796514933928847"> 1246 <ele>646.87109375</ele> 1247 </trkpt> 1248 <trkpt lat="47.18571729026735" lon="8.796522812917829"> 1249 <ele>646.1953125</ele> 1250 </trkpt> 1251 <trkpt lat="47.185757691040635" lon="8.796562207862735"> 1252 <ele>645.5859375</ele> 1253 </trkpt> 1254 <trkpt lat="47.18580354005098" lon="8.796577882021666"> 1255 <ele>644.8203125</ele> 1256 </trkpt> 1257 <trkpt lat="47.185914013534784" lon="8.796581821516156"> 1258 <ele>642.9765625</ele> 1259 </trkpt> 1260 <trkpt lat="47.18596254475415" lon="8.796625155955553"> 1261 <ele>641.796875</ele> 1262 </trkpt> 1263 <trkpt lat="47.186081148684025" lon="8.796644853428006"> 1264 <ele>639.4296875</ele> 1265 </trkpt> 1266 <trkpt lat="47.186186257749796" lon="8.7967315223068"> 1267 <ele>636.4921875</ele> 1268 </trkpt> 1269 <trkpt lat="47.186264377087355" lon="8.796790530905128"> 1270 <ele>634.1328125</ele> 1271 </trkpt> 1272 <trkpt lat="47.18639915809035" lon="8.796892957761884"> 1273 <ele>629.55859375</ele> 1274 </trkpt> 1275 <trkpt lat="47.186458418145776" lon="8.7969284132123"> 1276 <ele>627.55078125</ele> 1277 </trkpt> 1278 <trkpt lat="47.18660661019385" lon="8.796955989673734"> 1279 <ele>624.0234375</ele> 1280 </trkpt> 1281 </trkseg> 1282 </trk> 1283 <trk> 1284 <trkseg> 1285 <trkpt lat="47.18490038998425" lon="8.796944171190262"> 1286 <ele>663.90234375</ele> 1287 </trkpt> 1288 <trkpt lat="47.18495160341263" lon="8.796790530905128"> 1289 <ele>662.74609375</ele> 1290 </trkpt> 1291 <trkpt lat="47.18495696783066" lon="8.796640913933516"> 1292 <ele>662.1328125</ele> 1293 </trkpt> 1294 <trkpt lat="47.184981275349855" lon="8.796550389379263"> 1295 <ele>661.39453125</ele> 1296 </trkpt> 1297 <trkpt lat="47.18511060811579" lon="8.796479478478432"> 1298 <ele>658.98828125</ele> 1299 </trkpt> 1300 <trkpt lat="47.18521839939058" lon="8.7964085675776"> 1301 <ele>657.47265625</ele> 1302 </trkpt> 1303 <trkpt lat="47.18536122702062" lon="8.796420386061072"> 1304 <ele>654.22265625</ele> 1305 </trkpt> 1306 <trkpt lat="47.18553640879691" lon="8.796440083533525"> 1307 <ele>650.0703125</ele> 1308 </trkpt> 1309 <trkpt lat="47.185609163716435" lon="8.796475538983941"> 1310 <ele>647.890625</ele> 1311 </trkpt> 1312 </trkseg> 1313 </trk> 1314 <trk> 1315 <trkseg> 1316 <trkpt lat="47.20138901844621" lon="8.774476982653141"> 1317 <ele>421.52999999999997</ele> 1318 <time>2016-01-03T12:08:53.000Z</time> 1319 </trkpt> 1320 <trkpt lat="47.201492534950376" lon="8.773281471803784"> 1321 <ele>423.57999999999998</ele> 1322 <time>2016-01-03T12:09:10.000Z</time> 1323 </trkpt> 1324 <trkpt lat="47.2014878410846" lon="8.772208672016859"> 1325 <ele>423</ele> 1326 <time>2016-01-03T12:09:26.000Z</time> 1327 </trkpt> 1328 <trkpt lat="47.2014997433871" lon="8.772082105278969"> 1329 <ele>423.07999999999998</ele> 1330 <time>2016-01-03T12:09:28.000Z</time> 1331 </trkpt> 1332 <trkpt lat="47.2014896851033" lon="8.772034915164113"> 1333 <ele>423.02999999999997</ele> 1334 <time>2016-01-03T12:09:29.000Z</time> 1335 </trkpt> 1336 <trkpt lat="47.20144324935973" lon="8.77200884744525"> 1337 <ele>422.26999999999998</ele> 1338 <time>2016-01-03T12:09:31.000Z</time> 1339 </trkpt> 1340 <trkpt lat="47.201405949890614" lon="8.7720338255167"> 1341 <ele>421.35000000000002</ele> 1342 <time>2016-01-03T12:09:42.000Z</time> 1343 </trkpt> 1344 <trkpt lat="47.20132657326758" lon="8.771982276812196"> 1345 <ele>421.75</ele> 1346 <time>2016-01-03T12:10:04.000Z</time> 1347 </trkpt> 1348 <trkpt lat="47.20126815140247" lon="8.77192972227931"> 1349 <ele>421.48000000000002</ele> 1350 <time>2016-01-03T12:10:23.000Z</time> 1351 </trkpt> 1352 </trkseg> 1353 </trk> 1354 </gpx> 1355 No newline at end of file -
src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.data.gpx; 3 4 import java.util.ArrayList; 5 import java.util.Comparator; 6 import java.util.Date; 7 import java.util.List; 8 import java.util.concurrent.TimeUnit; 9 10 import org.openstreetmap.josm.gui.layer.geoimage.CorrelateGpxWithImages; 11 import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry; 12 import org.openstreetmap.josm.spi.preferences.Config; 13 import org.openstreetmap.josm.tools.Logging; 14 import org.openstreetmap.josm.tools.Pair; 15 16 /** 17 * Correlation logic for {@link CorrelateGpxWithImages} 18 */ 19 public class GpxImageCorrelation { 20 21 /** 22 * Match a list of photos to a gpx track with a given offset. 23 * All images need a exifTime attribute and the List must be sorted according to these times. 24 * @param images images to match 25 * @param selectedGpx selected GPX data 26 * @param offset offset 27 * @param forceTags force tagging of all photos, otherwise prefs are used 28 * @return number of matched points 29 * @since xxx 30 */ 31 public static int matchGpxTrack(List<ImageEntry> images, GpxData selectedGpx, long offset, boolean forceTags) { 32 int ret = 0; 33 34 long prevWpTime = 0; 35 WayPoint prevWp = null; 36 37 List<List<List<WayPoint>>> trks = new ArrayList<>(); 38 39 for (GpxTrack trk : selectedGpx.tracks) { 40 List<List<WayPoint>> segs = new ArrayList<>(); 41 for (GpxTrackSegment seg : trk.getSegments()) { 42 List<WayPoint> wps = new ArrayList<>(seg.getWayPoints()); 43 if (!wps.isEmpty()) { 44 //remove waypoints at the beginning of the track/segment without timestamps 45 int wp; 46 for (wp = 0; wp < wps.size(); wp++) { 47 if (wps.get(wp).setTimeFromAttribute() != null) { 48 break; 49 } 50 } 51 if (wp == 0) { 52 segs.add(wps); 53 } else if (wp < wps.size()) { 54 segs.add(wps.subList(wp, wps.size())); 55 } 56 } 57 } 58 //sort segments by first waypoint 59 if (!segs.isEmpty()) { 60 segs.sort(new Comparator<List<WayPoint>>() { 61 @Override 62 public int compare(List<WayPoint> arg0, List<WayPoint> arg1) { 63 if (arg0.isEmpty() || arg1.isEmpty() || arg0.get(0).time == arg1.get(0).time) 64 return 0; 65 return arg0.get(0).time < arg1.get(0).time ? -1 : 1; 66 } 67 }); 68 trks.add(segs); 69 } 70 } 71 //sort tracks by first waypoint of first segment 72 trks.sort(new Comparator<List<List<WayPoint>>>() { 73 @Override 74 public int compare(List<List<WayPoint>> arg0, List<List<WayPoint>> arg1) { 75 if (arg0.isEmpty() || arg0.get(0).isEmpty() 76 || arg1.isEmpty() || arg1.get(0).isEmpty() 77 || arg0.get(0).get(0).time == arg1.get(0).get(0).time) 78 return 0; 79 return arg0.get(0).get(0).time < arg1.get(0).get(0).time ? -1 : 1; 80 } 81 }); 82 83 boolean trkInt, trkTag, segInt, segTag; 84 int trkTime, trkDist, trkTagTime, segTime, segDist, segTagTime; 85 86 if (forceTags) { //temporary option to override advanced settings and activate all possible interpolations / tagging methods 87 trkInt = trkTag = segInt = segTag = true; 88 trkTime = trkDist = trkTagTime = segTime = segDist = segTagTime = Integer.MAX_VALUE; 89 } else { 90 // Load the settings 91 trkInt = Config.getPref().getBoolean("geoimage.trk.int", false); 92 trkTime = Config.getPref().getBoolean("geoimage.trk.int.time", false) ? Config.getPref().getInt("geoimage.trk.int.time.val", 60) : Integer.MAX_VALUE; 93 trkDist = Config.getPref().getBoolean("geoimage.trk.int.dist", false) ? Config.getPref().getInt("geoimage.trk.int.dist.val", 50) : Integer.MAX_VALUE; 94 95 trkTag = Config.getPref().getBoolean("geoimage.trk.tag", true); 96 trkTagTime = Config.getPref().getBoolean("geoimage.trk.tag.time", true) ? Config.getPref().getInt("geoimage.trk.tag.time.val", 2) : Integer.MAX_VALUE; 97 98 segInt = Config.getPref().getBoolean("geoimage.seg.int", true); 99 segTime = Config.getPref().getBoolean("geoimage.seg.int.time", true) ? Config.getPref().getInt("geoimage.seg.int.time.val", 60) : Integer.MAX_VALUE; 100 segDist = Config.getPref().getBoolean("geoimage.seg.int.dist", true) ? Config.getPref().getInt("geoimage.seg.int.dist.val", 50) : Integer.MAX_VALUE; 101 102 segTag = Config.getPref().getBoolean("geoimage.seg.tag", true); 103 segTagTime = Config.getPref().getBoolean("geoimage.seg.tag.time", true) ? Config.getPref().getInt("geoimage.seg.tag.time.val", 2) : Integer.MAX_VALUE; 104 } 105 boolean isFirst = true; 106 107 for (int t = 0; t < trks.size(); t++) { 108 List<List<WayPoint>> segs = trks.get(t); 109 for (int s = 0; s < segs.size(); s++) { 110 List<WayPoint> wps = segs.get(s); 111 for (int i = 0; i < wps.size(); i++) { 112 WayPoint curWp = wps.get(i); 113 Date parsedTime = curWp.setTimeFromAttribute(); 114 // Interpolate timestamps in the segment, if one or more waypoints miss them 115 if (parsedTime == null) { 116 //check if any of the following waypoints has a timestamp... 117 if (i > 0 && wps.get(i - 1).time != 0) { 118 long prevWpTimeNoOffset = wps.get(i - 1).getTime().getTime(); 119 double totalDist = 0; 120 List<Pair<Double, WayPoint>> nextWps = new ArrayList<>(); 121 for (int j = i; j < wps.size(); j++) { 122 totalDist += wps.get(j - 1).getCoor().greatCircleDistance(wps.get(j).getCoor()); 123 nextWps.add(new Pair<>(totalDist, wps.get(j))); 124 final Date nextTime = wps.get(j).setTimeFromAttribute(); 125 if (nextTime != null) { 126 // ...if yes, interpolate everything in between 127 long timeDiff = nextTime.getTime() - prevWpTimeNoOffset; 128 for (Pair<Double, WayPoint> pair : nextWps) { 129 pair.b.setTime(new Date((long) (prevWpTimeNoOffset + (timeDiff * (pair.a / totalDist))))); 130 } 131 break; 132 } 133 } 134 parsedTime = curWp.setTimeFromAttribute(); 135 if (parsedTime == null) { 136 break; //It's pointless to continue with this segment, because none of the following waypoints had a timestamp 137 } 138 } else { 139 continue; // Timestamps on waypoints without preceding timestamps in the same segment can not be interpolated, so try next one 140 } 141 } 142 143 final long curWpTime = parsedTime.getTime() + offset; 144 boolean interpolate = true; 145 int tagTime = 0; 146 if (i == 0) { 147 if (s == 0) { //First segment of the track, so apply settings for tracks 148 if (!trkInt || isFirst || prevWp == null || Math.abs(curWpTime - prevWpTime) > TimeUnit.MINUTES.toMillis(trkTime) || prevWp.getCoor().greatCircleDistance(curWp.getCoor()) > trkDist) { 149 isFirst = false; 150 interpolate = false; 151 if (trkTag) { 152 tagTime = trkTagTime; 153 } 154 } 155 } else { //Apply settings for segments 156 if (!segInt || prevWp == null || Math.abs(curWpTime - prevWpTime) > TimeUnit.MINUTES.toMillis(segTime) || prevWp.getCoor().greatCircleDistance(curWp.getCoor()) > segDist) { 157 interpolate = false; 158 if (segTag) { 159 tagTime = segTagTime; 160 } 161 } 162 } 163 } 164 ret += matchPoints(images, prevWp, prevWpTime, curWp, curWpTime, offset, interpolate, tagTime, false); 165 prevWp = curWp; 166 prevWpTime = curWpTime; 167 } 168 } 169 } 170 if (trkTag) { 171 ret += matchPoints(images, prevWp, prevWpTime, prevWp, prevWpTime, offset, false, trkTagTime, true); 172 } 173 return ret; 174 } 175 176 private static Double getElevation(WayPoint wp) { 177 String value = wp.getString(GpxConstants.PT_ELE); 178 if (value != null && !value.isEmpty()) { 179 try { 180 return Double.valueOf(value); 181 } catch (NumberFormatException e) { 182 Logging.warn(e); 183 } 184 } 185 return null; 186 } 187 188 private static int matchPoints(List<ImageEntry> images, WayPoint prevWp, long prevWpTime, WayPoint curWp, long curWpTime, 189 long offset, boolean interpolate, int tagTime, boolean isLast) { 190 191 int ret = 0; 192 193 // i is the index of the timewise last photo that has the same or earlier EXIF time 194 int i; 195 if (isLast) { 196 i = images.size() - 1; 197 } else { 198 i = getLastIndexOfListBefore(images, curWpTime); 199 } 200 201 // no photos match 202 if (i < 0) 203 return 0; 204 205 Double speed = null; 206 Double prevElevation = null; 207 208 if (prevWp != null && interpolate) { 209 double distance = prevWp.getCoor().greatCircleDistance(curWp.getCoor()); 210 // This is in km/h, 3.6 * m/s 211 if (curWpTime > prevWpTime) { 212 speed = 3600 * distance / (curWpTime - prevWpTime); 213 } 214 prevElevation = getElevation(prevWp); 215 } 216 217 Double curElevation = getElevation(curWp); 218 219 if (!interpolate || isLast) { 220 final long half = Math.abs(curWpTime - prevWpTime) / 2; 221 while (i >= 0) { 222 final ImageEntry curImg = images.get(i); 223 final ImageEntry curTmp = curImg.getTmp(); 224 final long time = curImg.getExifTime().getTime(); 225 if ((!isLast && time > curWpTime) || time < prevWpTime) { 226 break; 227 } 228 long tagms = TimeUnit.MINUTES.toMillis(tagTime); 229 if (curTmp.getPos() == null && 230 (Math.abs(time - curWpTime) <= tagms 231 || Math.abs(prevWpTime - time) <= tagms)) { 232 if (prevWp != null && time < curWpTime - half) { 233 curTmp.setPos(prevWp.getCoor()); 234 } else { 235 curTmp.setPos(curWp.getCoor()); 236 } 237 curTmp.setGpsTime(new Date(curImg.getExifTime().getTime() - offset)); 238 curTmp.flagNewGpsData(); 239 ret++; 240 } 241 i--; 242 } 243 } else if (prevWp != null) { 244 // This code gives a simple linear interpolation of the coordinates between current and 245 // previous track point assuming a constant speed in between 246 while (i >= 0) { 247 ImageEntry curImg = images.get(i); 248 ImageEntry curTmp = curImg.getTmp(); 249 final long imgTime = curImg.getExifTime().getTime(); 250 if (imgTime < prevWpTime) { 251 break; 252 } 253 if (curTmp.getPos() == null) { 254 // The values of timeDiff are between 0 and 1, it is not seconds but a dimensionless variable 255 double timeDiff = (double) (imgTime - prevWpTime) / Math.abs(curWpTime - prevWpTime); 256 curTmp.setPos(prevWp.getCoor().interpolate(curWp.getCoor(), timeDiff)); 257 curTmp.setSpeed(speed); 258 if (curElevation != null && prevElevation != null) { 259 curTmp.setElevation(prevElevation + (curElevation - prevElevation) * timeDiff); 260 } 261 curTmp.setGpsTime(new Date(curImg.getExifTime().getTime() - offset)); 262 curTmp.flagNewGpsData(); 263 264 ret++; 265 } 266 i--; 267 } 268 } 269 return ret; 270 } 271 272 private static int getLastIndexOfListBefore(List<ImageEntry> images, long searchedTime) { 273 int lstSize = images.size(); 274 275 // No photos or the first photo taken is later than the search period 276 if (lstSize == 0 || searchedTime < images.get(0).getExifTime().getTime()) 277 return -1; 278 279 // The search period is later than the last photo 280 if (searchedTime > images.get(lstSize - 1).getExifTime().getTime()) 281 return lstSize-1; 282 283 // The searched index is somewhere in the middle, do a binary search from the beginning 284 int curIndex; 285 int startIndex = 0; 286 int endIndex = lstSize-1; 287 while (endIndex - startIndex > 1) { 288 curIndex = (endIndex + startIndex) / 2; 289 if (searchedTime > images.get(curIndex).getExifTime().getTime()) { 290 startIndex = curIndex; 291 } else { 292 endIndex = curIndex; 293 } 294 } 295 if (searchedTime < images.get(endIndex).getExifTime().getTime()) 296 return startIndex; 297 298 // This final loop is to check if photos with the exact same EXIF time follows 299 while ((endIndex < (lstSize - 1)) && (images.get(endIndex).getExifTime().getTime() 300 == images.get(endIndex + 1).getExifTime().getTime())) { 301 endIndex++; 302 } 303 return endIndex; 304 } 305 306 } -
src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
5 5 import static org.openstreetmap.josm.tools.I18n.trn; 6 6 7 7 import java.awt.BorderLayout; 8 import java.awt.Component; 8 9 import java.awt.Cursor; 9 10 import java.awt.Dimension; 10 11 import java.awt.FlowLayout; … … 43 44 import javax.swing.BorderFactory; 44 45 import javax.swing.JButton; 45 46 import javax.swing.JCheckBox; 47 import javax.swing.JComponent; 46 48 import javax.swing.JFileChooser; 47 49 import javax.swing.JLabel; 48 50 import javax.swing.JList; … … 51 53 import javax.swing.JScrollPane; 52 54 import javax.swing.JSeparator; 53 55 import javax.swing.JSlider; 56 import javax.swing.JSpinner; 54 57 import javax.swing.ListSelectionModel; 55 58 import javax.swing.MutableComboBoxModel; 59 import javax.swing.SpinnerNumberModel; 56 60 import javax.swing.SwingConstants; 61 import javax.swing.border.Border; 57 62 import javax.swing.event.ChangeEvent; 58 63 import javax.swing.event.ChangeListener; 59 64 import javax.swing.event.DocumentEvent; … … 61 66 62 67 import org.openstreetmap.josm.actions.DiskAccessAction; 63 68 import org.openstreetmap.josm.actions.ExtensionFileFilter; 64 import org.openstreetmap.josm.data.gpx.GpxConstants;65 69 import org.openstreetmap.josm.data.gpx.GpxData; 70 import org.openstreetmap.josm.data.gpx.GpxImageCorrelation; 66 71 import org.openstreetmap.josm.data.gpx.GpxTrack; 67 72 import org.openstreetmap.josm.data.gpx.GpxTrackSegment; 68 73 import org.openstreetmap.josm.data.gpx.WayPoint; … … 74 79 import org.openstreetmap.josm.gui.io.importexport.NMEAImporter; 75 80 import org.openstreetmap.josm.gui.layer.GpxLayer; 76 81 import org.openstreetmap.josm.gui.layer.Layer; 82 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent; 83 import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener; 84 import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent; 85 import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent; 77 86 import org.openstreetmap.josm.gui.widgets.AbstractFileChooser; 78 87 import org.openstreetmap.josm.gui.widgets.FileChooserManager; 79 88 import org.openstreetmap.josm.gui.widgets.JosmComboBox; … … 83 92 import org.openstreetmap.josm.io.IGpxReader; 84 93 import org.openstreetmap.josm.io.nmea.NmeaReader; 85 94 import org.openstreetmap.josm.spi.preferences.Config; 95 import org.openstreetmap.josm.spi.preferences.IPreferences; 86 96 import org.openstreetmap.josm.tools.GBC; 87 97 import org.openstreetmap.josm.tools.ImageProvider; 88 98 import org.openstreetmap.josm.tools.JosmRuntimeException; … … 102 112 private final transient GeoImageLayer yLayer; 103 113 private transient Timezone timezone; 104 114 private transient Offset delta; 115 private static boolean forceTags = false; 105 116 106 117 /** 107 118 * Constructs a new {@code CorrelateGpxWithImages} action. … … 111 122 super(tr("Correlate to GPX")); 112 123 new ImageProvider("dialogs/geoimage/gpx2img").getResource().attachImageIcon(this, true); 113 124 this.yLayer = layer; 125 MainApplication.getLayerManager().addLayerChangeListener(new GpxLayerAddedListener()); 114 126 } 115 127 116 128 private final class SyncDialogWindowListener extends WindowAdapter { … … 322 334 } 323 335 } 324 336 337 private class AdvancedSettingsActionListener implements ActionListener { 338 339 private class CheckBoxActionListener implements ActionListener { 340 private JComponent[] comps; 341 342 CheckBoxActionListener(JComponent... c) { 343 comps = c; 344 } 345 346 @Override 347 public void actionPerformed(ActionEvent arg0) { 348 setEnabled((JCheckBox) arg0.getSource()); 349 } 350 351 public void setEnabled(JCheckBox cb) { 352 for (JComponent comp : comps) { 353 if (comp instanceof JSpinner) { 354 comp.setEnabled(cb.isSelected()); 355 } else if (comp instanceof JPanel) { 356 boolean en = cb.isSelected(); 357 for (Component c : comp.getComponents()) { 358 if (c instanceof JSpinner) { 359 c.setEnabled(en); 360 } else { 361 c.setEnabled(cb.isSelected()); 362 if (en && c instanceof JCheckBox) { 363 en = ((JCheckBox) c).isSelected(); 364 } 365 } 366 } 367 } 368 } 369 370 } 371 } 372 373 private void addCheckBoxActionListener(JCheckBox cb, JComponent... c) { 374 CheckBoxActionListener listener = new CheckBoxActionListener(c); 375 cb.addActionListener(listener); 376 listener.setEnabled(cb); 377 } 378 379 @Override 380 public void actionPerformed(ActionEvent arg0) { 381 382 IPreferences s = Config.getPref(); 383 JPanel p = new JPanel(new GridBagLayout()); 384 385 Border border1 = BorderFactory.createEmptyBorder(0, 20, 0, 0); 386 Border border2 = BorderFactory.createEmptyBorder(10, 0, 5, 0); 387 Border border = BorderFactory.createEmptyBorder(0, 40, 0, 0); 388 FlowLayout layout = new FlowLayout(); 389 390 JLabel l = new JLabel(tr("Segment settings")); 391 l.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); 392 p.add(l, GBC.eol()); 393 JCheckBox cInterpolSeg = new JCheckBox(tr("Interpolate between segments"), s.getBoolean("geoimage.seg.int", true)); 394 cInterpolSeg.setBorder(border1); 395 p.add(cInterpolSeg, GBC.eol()); 396 397 String[] trs = tr("only when the segments are less than # minutes apart").split("#"); 398 JCheckBox cInterpolSegTime = new JCheckBox(trs[0].trim(), s.getBoolean("geoimage.seg.int.time", true)); 399 JSpinner sInterpolSegTime = new JSpinner(new SpinnerNumberModel(s.getInt("geoimage.seg.int.time.val", 60), 0, Integer.MAX_VALUE, 1)); 400 ((JSpinner.DefaultEditor) sInterpolSegTime.getEditor()).getTextField().setColumns(3); 401 JLabel lInterpolSegTime = new JLabel(trs.length >= 2 ? trs[1].trim() : ""); 402 JPanel pInterpolSegTime = new JPanel(layout); 403 pInterpolSegTime.add(cInterpolSegTime); 404 pInterpolSegTime.add(sInterpolSegTime); 405 pInterpolSegTime.add(lInterpolSegTime); 406 pInterpolSegTime.setBorder(border); 407 p.add(pInterpolSegTime, GBC.eol()); 408 409 trs = tr("only when the segments are less than # metres apart").split("#"); 410 JCheckBox cInterpolSegDist = new JCheckBox(trs[0].trim(), s.getBoolean("geoimage.seg.int.dist", true)); 411 JSpinner sInterpolSegDist = new JSpinner(new SpinnerNumberModel(s.getInt("geoimage.seg.int.dist.val", 50), 0, Integer.MAX_VALUE, 1)); 412 ((JSpinner.DefaultEditor) sInterpolSegDist.getEditor()).getTextField().setColumns(3); 413 JLabel lInterpolSegDist = new JLabel(trs.length >= 2 ? trs[1].trim() : ""); 414 JPanel pInterpolSegDist = new JPanel(layout); 415 pInterpolSegDist.add(cInterpolSegDist); 416 pInterpolSegDist.add(sInterpolSegDist); 417 pInterpolSegDist.add(lInterpolSegDist); 418 pInterpolSegDist.setBorder(border); 419 p.add(pInterpolSegDist, GBC.eol()); 420 421 JCheckBox cTagSeg = new JCheckBox(tr("Tag images at the closest end of a segment, when not interpolated"), s.getBoolean("geoimage.seg.tag", true)); 422 cTagSeg.setBorder(border1); 423 p.add(cTagSeg, GBC.eol()); 424 425 trs = tr("only within # minutes of the closest trackpoint").split("#"); 426 JCheckBox cTagSegTime = new JCheckBox(trs[0].trim(), s.getBoolean("geoimage.seg.tag.time", true)); 427 JSpinner sTagSegTime = new JSpinner(new SpinnerNumberModel(s.getInt("geoimage.seg.tag.time.val", 2), 0, Integer.MAX_VALUE, 1)); 428 ((JSpinner.DefaultEditor) sTagSegTime.getEditor()).getTextField().setColumns(3); 429 JLabel lTagSegTime = new JLabel(trs.length >= 2 ? trs[1].trim() : ""); 430 JPanel pTagSegTime = new JPanel(layout); 431 pTagSegTime.add(cTagSegTime); 432 pTagSegTime.add(sTagSegTime); 433 pTagSegTime.add(lTagSegTime); 434 pTagSegTime.setBorder(border); 435 p.add(pTagSegTime, GBC.eol()); 436 437 l = new JLabel(tr("Track settings (note that multiple tracks can be in one GPX file)")); 438 l.setBorder(border2); 439 p.add(l, GBC.eol()); 440 JCheckBox cInterpolTrack = new JCheckBox(tr("Interpolate between tracks"), s.getBoolean("geoimage.trk.int", false)); 441 cInterpolTrack.setBorder(border1); 442 p.add(cInterpolTrack, GBC.eol()); 443 444 trs = tr("only when the tracks are less than # minutes apart").split("#"); 445 JCheckBox cInterpolTrackTime = new JCheckBox(trs[0].trim(), s.getBoolean("geoimage.trk.int.time", false)); 446 JSpinner sInterpolTrackTime = new JSpinner(new SpinnerNumberModel(s.getInt("geoimage.trk.int.time.val", 60), 0, Integer.MAX_VALUE, 1)); 447 ((JSpinner.DefaultEditor) sInterpolTrackTime.getEditor()).getTextField().setColumns(3); 448 JLabel lInterpolTrackTime = new JLabel(trs.length >= 2 ? trs[1].trim() : ""); 449 JPanel pInterpolTrackTime = new JPanel(layout); 450 pInterpolTrackTime.add(cInterpolTrackTime); 451 pInterpolTrackTime.add(sInterpolTrackTime); 452 pInterpolTrackTime.add(lInterpolTrackTime); 453 pInterpolTrackTime.setBorder(border); 454 p.add(pInterpolTrackTime, GBC.eol()); 455 456 trs = tr("only when the tracks are less than # metres apart").split("#"); 457 JCheckBox cInterpolTrackDist = new JCheckBox(trs[0].trim(), s.getBoolean("geoimage.trk.int.dist", false)); 458 JSpinner sInterpolTrackDist = new JSpinner(new SpinnerNumberModel(s.getInt("geoimage.trk.int.dist.val", 50), 0, Integer.MAX_VALUE, 1)); 459 ((JSpinner.DefaultEditor) sInterpolTrackDist.getEditor()).getTextField().setColumns(3); 460 JLabel lInterpolTrackDist = new JLabel(trs.length >= 2 ? trs[1].trim() : ""); 461 JPanel pInterpolTrackDist = new JPanel(layout); 462 pInterpolTrackDist.add(cInterpolTrackDist); 463 pInterpolTrackDist.add(sInterpolTrackDist); 464 pInterpolTrackDist.add(lInterpolTrackDist); 465 pInterpolTrackDist.setBorder(border); 466 p.add(pInterpolTrackDist, GBC.eol()); 467 468 JCheckBox cTagTrack = new JCheckBox(tr("<html>Tag images at the closest end of a track, when not interpolated<br>" + 469 "(also applies before the first and after the last track)</html>"), s.getBoolean("geoimage.trk.tag", true)); 470 cTagTrack.setBorder(border1); 471 p.add(cTagTrack, GBC.eol()); 472 473 trs = tr("only within # minutes of the closest trackpoint").split("#"); 474 JCheckBox cTagTrackTime = new JCheckBox(trs[0].trim(), s.getBoolean("geoimage.trk.tag.time", true)); 475 JSpinner sTagTrackTime = new JSpinner(new SpinnerNumberModel(s.getInt("geoimage.trk.tag.time.val", 2), 0, Integer.MAX_VALUE, 1)); 476 ((JSpinner.DefaultEditor) sTagTrackTime.getEditor()).getTextField().setColumns(3); 477 JLabel lTagTrackTime = new JLabel(trs.length >= 2 ? trs[1].trim() : ""); 478 JPanel pTagTrackTime = new JPanel(layout); 479 pTagTrackTime.add(cTagTrackTime); 480 pTagTrackTime.add(sTagTrackTime); 481 pTagTrackTime.add(lTagTrackTime); 482 pTagTrackTime.setBorder(border); 483 p.add(pTagTrackTime, GBC.eol()); 484 485 l = new JLabel(tr("Advanced")); 486 l.setBorder(border2); 487 p.add(l, GBC.eol()); 488 JCheckBox cForce = new JCheckBox(tr("<html>Force tagging of all pictures (temporarily overrides the settings above)<br>This option will not be saved permanently</html>"), forceTags); 489 cForce.setBorder(BorderFactory.createEmptyBorder(0, 20, 10, 0)); 490 p.add(cForce, GBC.eol()); 491 492 addCheckBoxActionListener(cInterpolSegTime, sInterpolSegTime); 493 addCheckBoxActionListener(cInterpolSegDist, sInterpolSegDist); 494 addCheckBoxActionListener(cInterpolSeg, pInterpolSegTime, pInterpolSegDist); 495 496 addCheckBoxActionListener(cTagSegTime, sTagSegTime); 497 addCheckBoxActionListener(cTagSeg, pTagSegTime); 498 499 addCheckBoxActionListener(cInterpolTrackTime, sInterpolTrackTime); 500 addCheckBoxActionListener(cInterpolTrackDist, sInterpolTrackDist); 501 addCheckBoxActionListener(cInterpolTrack, pInterpolTrackTime, pInterpolTrackDist); 502 503 addCheckBoxActionListener(cTagTrackTime, sTagTrackTime); 504 addCheckBoxActionListener(cTagTrack, pTagTrackTime); 505 506 507 ExtendedDialog ed = new ExtendedDialog(MainApplication.getMainFrame(), tr("Advanced settings"), tr("OK"), tr("Cancel")) 508 .setButtonIcons("ok", "cancel").setContent(p); 509 if (ed.showDialog().getValue() == 1) { 510 511 s.putBoolean("geoimage.seg.int", cInterpolSeg.isSelected()); 512 s.putBoolean("geoimage.seg.int.dist", cInterpolSegDist.isSelected()); 513 s.putInt("geoimage.seg.int.dist.val", (int) sInterpolSegDist.getValue()); 514 s.putBoolean("geoimage.seg.int.time", cInterpolSegTime.isSelected()); 515 s.putInt("geoimage.seg.int.time.val", (int) sInterpolSegTime.getValue()); 516 s.putBoolean("geoimage.seg.tag", cTagSeg.isSelected()); 517 s.putBoolean("geoimage.seg.tag.time", cTagSegTime.isSelected()); 518 s.putInt("geoimage.seg.tag.time.val", (int) sTagSegTime.getValue()); 519 520 s.putBoolean("geoimage.trk.int", cInterpolTrack.isSelected()); 521 s.putBoolean("geoimage.trk.int.dist", cInterpolTrackDist.isSelected()); 522 s.putInt("geoimage.trk.int.dist.val", (int) sInterpolTrackDist.getValue()); 523 s.putBoolean("geoimage.trk.int.time", cInterpolTrackTime.isSelected()); 524 s.putInt("geoimage.trk.int.time.val", (int) sInterpolTrackTime.getValue()); 525 s.putBoolean("geoimage.trk.tag", cTagTrack.isSelected()); 526 s.putBoolean("geoimage.trk.tag.time", cTagTrackTime.isSelected()); 527 s.putInt("geoimage.trk.tag.time.val", (int) sTagTrackTime.getValue()); 528 529 forceTags = cForce.isSelected(); // This setting is not supposed to be saved permanently 530 531 statusBarUpdater.updateStatusBar(); 532 yLayer.updateBufferAndRepaint(); 533 } 534 } 535 536 } 537 325 538 /** 326 539 * This action listener is called when the user has a photo of the time of his GPS receiver. It 327 540 * displays the list of photos of the layer, and upon selection displays the selected photo. … … 525 738 } 526 739 } 527 740 741 private class GpxLayerAddedListener implements LayerChangeListener { 742 @Override 743 public void layerAdded(LayerAddEvent e) { 744 if (syncDialog != null && syncDialog.isVisible()) { 745 Layer layer = e.getAddedLayer(); 746 if (layer instanceof GpxLayer) { 747 GpxLayer gpx = (GpxLayer) layer; 748 GpxDataWrapper gdw = new GpxDataWrapper(gpx.getName(), gpx.data, gpx.data.storageFile); 749 gpxLst.add(gdw); 750 MutableComboBoxModel<GpxDataWrapper> model = (MutableComboBoxModel<GpxDataWrapper>) cbGpx.getModel(); 751 if (gpxLst.get(0).file == null) { 752 gpxLst.remove(0); 753 model.removeElementAt(0); 754 } 755 model.addElement(gdw); 756 } 757 } 758 } 759 @Override 760 public void layerRemoving(LayerRemoveEvent e) {} 761 @Override 762 public void layerOrderChanged(LayerOrderChangeEvent e) {} 763 } 764 528 765 @Override 529 766 public void actionPerformed(ActionEvent ae) { 530 767 // Construct the list of loaded GPX tracks … … 606 843 JButton buttonAdjust = new JButton(tr("Manual adjust")); 607 844 buttonAdjust.addActionListener(new AdjustActionListener()); 608 845 846 JButton buttonAdvanced = new JButton(tr("Advanced settings...")); 847 buttonAdvanced.addActionListener(new AdvancedSettingsActionListener()); 848 609 849 JLabel labelPosition = new JLabel(tr("Override position for: ")); 610 850 611 851 int numAll = getSortedImgList(true, true).size(); … … 666 906 gbc.weightx = 0.5; 667 907 panelTf.add(buttonViewGpsPhoto, gbc); 668 908 909 669 910 gbc = GBC.std().fill(GBC.BOTH).insets(5, 5, 5, 5); 670 gbc.gridx = 2;911 gbc.gridx = 1; 671 912 gbc.gridy = y++; 672 913 gbc.weightx = 0.5; 914 panelTf.add(buttonAdvanced, gbc); 915 916 gbc.gridx = 2; 673 917 panelTf.add(buttonAutoGuess, gbc); 674 918 675 919 gbc.gridx = 3; … … 715 959 cbTaggedImg.addItemListener(statusBarUpdaterWithRepaint); 716 960 717 961 statusBarUpdater.updateStatusBar(); 962 yLayer.updateBufferAndRepaint(); 718 963 719 964 outerPanel = new JPanel(new BorderLayout()); 720 965 outerPanel.add(statusBar, BorderLayout.PAGE_END); … … 807 1052 if (selGpx == null) 808 1053 return tr("No gpx selected"); 809 1054 810 final long offsetMs = ((long) (timezone.getHours() * TimeUnit.HOURS.toMillis( 1))) + delta.getMilliseconds(); // in milliseconds811 lastNumMatched = matchGpxTrack(dateImgLst, selGpx.data, offsetMs);1055 final long offsetMs = ((long) (timezone.getHours() * TimeUnit.HOURS.toMillis(-1))) + delta.getMilliseconds(); // in milliseconds 1056 lastNumMatched = GpxImageCorrelation.matchGpxTrack(dateImgLst, selGpx.data, offsetMs, forceTags); 812 1057 813 1058 return trn("<html>Matched <b>{0}</b> of <b>{1}</b> photo to GPX track.</html>", 814 1059 "<html>Matched <b>{0}</b> of <b>{1}</b> photos to GPX track.</html>", … … 1036 1281 yLayer.updateBufferAndRepaint(); 1037 1282 } 1038 1283 } 1039 1040 1284 private List<ImageEntry> getSortedImgList() { 1041 1285 return getSortedImgList(cbExifImg.isSelected(), cbTaggedImg.isSelected()); 1042 1286 } … … 1087 1331 return (GpxDataWrapper) item; 1088 1332 } 1089 1333 1090 /**1091 * Match a list of photos to a gpx track with a given offset.1092 * All images need a exifTime attribute and the List must be sorted according to these times.1093 * @param images images to match1094 * @param selectedGpx selected GPX data1095 * @param offset offset1096 * @return number of matched points1097 */1098 static int matchGpxTrack(List<ImageEntry> images, GpxData selectedGpx, long offset) {1099 int ret = 0;1100 1101 for (GpxTrack trk : selectedGpx.tracks) {1102 for (GpxTrackSegment segment : trk.getSegments()) {1103 1104 long prevWpTime = 0;1105 WayPoint prevWp = null;1106 1107 for (WayPoint curWp : segment.getWayPoints()) {1108 final Date parsedTime = curWp.setTimeFromAttribute();1109 if (parsedTime != null) {1110 final long curWpTime = parsedTime.getTime() + offset;1111 ret += matchPoints(images, prevWp, prevWpTime, curWp, curWpTime, offset);1112 1113 prevWp = curWp;1114 prevWpTime = curWpTime;1115 continue;1116 }1117 prevWp = null;1118 prevWpTime = 0;1119 }1120 }1121 }1122 return ret;1123 }1124 1125 private static Double getElevation(WayPoint wp) {1126 String value = wp.getString(GpxConstants.PT_ELE);1127 if (value != null && !value.isEmpty()) {1128 try {1129 return Double.valueOf(value);1130 } catch (NumberFormatException e) {1131 Logging.warn(e);1132 }1133 }1134 return null;1135 }1136 1137 static int matchPoints(List<ImageEntry> images, WayPoint prevWp, long prevWpTime,1138 WayPoint curWp, long curWpTime, long offset) {1139 // Time between the track point and the previous one, 5 sec if first point, i.e. photos take1140 // 5 sec before the first track point can be assumed to be take at the starting position1141 long interval = prevWpTime > 0 ? Math.abs(curWpTime - prevWpTime) : TimeUnit.SECONDS.toMillis(5);1142 int ret = 0;1143 1144 // i is the index of the timewise last photo that has the same or earlier EXIF time1145 int i = getLastIndexOfListBefore(images, curWpTime);1146 1147 // no photos match1148 if (i < 0)1149 return 0;1150 1151 Double speed = null;1152 Double prevElevation = null;1153 1154 if (prevWp != null) {1155 double distance = prevWp.getCoor().greatCircleDistance(curWp.getCoor());1156 // This is in km/h, 3.6 * m/s1157 if (curWpTime > prevWpTime) {1158 speed = 3600 * distance / (curWpTime - prevWpTime);1159 }1160 prevElevation = getElevation(prevWp);1161 }1162 1163 Double curElevation = getElevation(curWp);1164 1165 // First trackpoint, then interval is set to five seconds, i.e. photos up to five seconds1166 // before the first point will be geotagged with the starting point1167 if (prevWpTime == 0 || curWpTime <= prevWpTime) {1168 while (i >= 0) {1169 final ImageEntry curImg = images.get(i);1170 long time = curImg.getExifTime().getTime();1171 if (time > curWpTime || time < curWpTime - interval) {1172 break;1173 }1174 if (curImg.tmp.getPos() == null) {1175 curImg.tmp.setPos(curWp.getCoor());1176 curImg.tmp.setSpeed(speed);1177 curImg.tmp.setElevation(curElevation);1178 curImg.tmp.setGpsTime(new Date(curImg.getExifTime().getTime() - offset));1179 curImg.tmp.flagNewGpsData();1180 ret++;1181 }1182 i--;1183 }1184 return ret;1185 }1186 1187 // This code gives a simple linear interpolation of the coordinates between current and1188 // previous track point assuming a constant speed in between1189 while (i >= 0) {1190 ImageEntry curImg = images.get(i);1191 long imgTime = curImg.getExifTime().getTime();1192 if (imgTime < prevWpTime) {1193 break;1194 }1195 1196 if (prevWp != null && curImg.tmp.getPos() == null) {1197 // The values of timeDiff are between 0 and 1, it is not seconds but a dimensionless variable1198 double timeDiff = (double) (imgTime - prevWpTime) / interval;1199 curImg.tmp.setPos(prevWp.getCoor().interpolate(curWp.getCoor(), timeDiff));1200 curImg.tmp.setSpeed(speed);1201 if (curElevation != null && prevElevation != null) {1202 curImg.tmp.setElevation(prevElevation + (curElevation - prevElevation) * timeDiff);1203 }1204 curImg.tmp.setGpsTime(new Date(curImg.getExifTime().getTime() - offset));1205 curImg.tmp.flagNewGpsData();1206 1207 ret++;1208 }1209 i--;1210 }1211 return ret;1212 }1213 1214 private static int getLastIndexOfListBefore(List<ImageEntry> images, long searchedTime) {1215 int lstSize = images.size();1216 1217 // No photos or the first photo taken is later than the search period1218 if (lstSize == 0 || searchedTime < images.get(0).getExifTime().getTime())1219 return -1;1220 1221 // The search period is later than the last photo1222 if (searchedTime > images.get(lstSize - 1).getExifTime().getTime())1223 return lstSize-1;1224 1225 // The searched index is somewhere in the middle, do a binary search from the beginning1226 int curIndex;1227 int startIndex = 0;1228 int endIndex = lstSize-1;1229 while (endIndex - startIndex > 1) {1230 curIndex = (endIndex + startIndex) / 2;1231 if (searchedTime > images.get(curIndex).getExifTime().getTime()) {1232 startIndex = curIndex;1233 } else {1234 endIndex = curIndex;1235 }1236 }1237 if (searchedTime < images.get(endIndex).getExifTime().getTime())1238 return startIndex;1239 1240 // This final loop is to check if photos with the exact same EXIF time follows1241 while ((endIndex < (lstSize-1)) && (images.get(endIndex).getExifTime().getTime()1242 == images.get(endIndex + 1).getExifTime().getTime())) {1243 endIndex++;1244 }1245 return endIndex;1246 }1247 1334 } -
src/org/openstreetmap/josm/gui/layer/geoimage/Timezone.java
5 5 6 6 import java.text.ParseException; 7 7 import java.util.Objects; 8 import java.util.regex.Matcher; 9 import java.util.regex.Pattern; 8 10 9 11 /** 10 12 * Timezone in hours.<p> … … 49 51 } 50 52 51 53 static Timezone parseTimezone(String timezone) throws ParseException { 52 53 54 if (timezone.isEmpty()) 54 55 return ZERO; 55 56 56 String error = tr("Error while parsing timezone.\nExpected format: {0}", "+H:MM");57 Matcher m = Pattern.compile("^([\\+\\-]?)(\\d{1,2})(?:\\:([0-5]\\d))?$").matcher(timezone); 57 58 58 char sgnTimezone = '+'; 59 StringBuilder hTimezone = new StringBuilder(); 60 StringBuilder mTimezone = new StringBuilder(); 61 int state = 1; // 1=start/sign, 2=hours, 3=minutes. 62 for (int i = 0; i < timezone.length(); i++) { 63 char c = timezone.charAt(i); 64 switch (c) { 65 case ' ': 66 if (state != 2 || hTimezone.length() != 0) 67 throw new ParseException(error, i); 68 break; 69 case '+': 70 case '-': 71 if (state == 1) { 72 sgnTimezone = c; 73 state = 2; 74 } else 75 throw new ParseException(error, i); 76 break; 77 case ':': 78 case '.': 79 if (state == 2) { 80 state = 3; 81 } else 82 throw new ParseException(error, i); 83 break; 84 case '0': 85 case '1': 86 case '2': 87 case '3': 88 case '4': 89 case '5': 90 case '6': 91 case '7': 92 case '8': 93 case '9': 94 switch (state) { 95 case 1: 96 case 2: 97 state = 2; 98 hTimezone.append(c); 99 break; 100 case 3: 101 mTimezone.append(c); 102 break; 103 default: 104 throw new ParseException(error, i); 105 } 106 break; 107 default: 108 throw new ParseException(error, i); 109 } 110 } 111 112 int h = 0; 113 int m = 0; 59 ParseException pe = new ParseException(tr("Error while parsing timezone.\nExpected format: {0}", "±HH:MM"), 0); 114 60 try { 115 h = Integer.parseInt(hTimezone.toString()); 116 if (mTimezone.length() > 0) { 117 m = Integer.parseInt(mTimezone.toString()); 61 if (m.find()) { 62 int sign = m.group(1) == "-" ? -1 : 1; 63 int hour = Integer.parseInt(m.group(2)); 64 int min = m.groupCount() > 3 ? Integer.parseInt(m.group(3)) : 0; 65 return new Timezone(sign * hour + min / 60.0); 118 66 } 119 } catch (NumberFormatException nfe) { 120 // Invalid timezone 121 throw (ParseException) new ParseException(error, 0).initCause(nfe); 67 } catch (IndexOutOfBoundsException | NumberFormatException ex) { 68 pe.initCause(ex); 122 69 } 123 124 if (h > 12 || m > 59) 125 throw new ParseException(error, 0); 126 else 127 return new Timezone((h + m / 60.0) * (sgnTimezone == '-' ? -1 : 1)); 70 throw pe; 128 71 } 129 72 130 73 @Override -
test/unit/org/openstreetmap/josm/data/gpx/GpxImageCorrelationTest.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.data.gpx; 3 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertFalse; 6 import static org.junit.Assert.assertTrue; 7 8 import java.util.Arrays; 9 import java.util.List; 10 11 import org.junit.BeforeClass; 12 import org.junit.Rule; 13 import org.junit.Test; 14 import org.openstreetmap.josm.data.coor.CachedLatLon; 15 import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry; 16 import org.openstreetmap.josm.io.GpxReaderTest; 17 import org.openstreetmap.josm.spi.preferences.Config; 18 import org.openstreetmap.josm.spi.preferences.IPreferences; 19 import org.openstreetmap.josm.testutils.JOSMTestRules; 20 import org.openstreetmap.josm.tools.date.DateUtils; 21 import org.openstreetmap.josm.tools.date.DateUtilsTest; 22 23 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 24 25 /** 26 * Unit tests of {@link GpxImageCorrelation} class. 27 */ 28 public class GpxImageCorrelationTest { 29 30 /** 31 * Setup test. 32 */ 33 @Rule 34 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 35 public JOSMTestRules test = new JOSMTestRules(); 36 37 /** 38 * Setup test. 39 */ 40 @BeforeClass 41 public static void setUp() { 42 DateUtilsTest.setTimeZone(DateUtils.UTC); 43 } 44 45 /** 46 * Tests matching of images to a GPX track. 47 * @throws Exception if the track cannot be parsed 48 */ 49 @Test 50 public void testMatchGpxTrack() throws Exception { 51 IPreferences s = Config.getPref(); 52 final GpxData gpx = GpxReaderTest.parseGpxData("data_nodist/ImageCorrelationTest.gpx"); 53 assertEquals(5, gpx.tracks.size()); 54 assertEquals(1, gpx.tracks.iterator().next().getSegments().size()); 55 assertEquals(128, gpx.tracks.iterator().next().getSegments().iterator().next().getWayPoints().size()); 56 57 final ImageEntry ib = new ImageEntry(); 58 ib.setExifTime(DateUtils.fromString("2016:01:03 11:54:58")); // 5 minutes before start of GPX 59 ib.createTmp(); 60 final ImageEntry i0 = new ImageEntry(); 61 i0.setExifTime(DateUtils.fromString("2016:01:03 11:59:54")); // 4 sec before start of GPX 62 i0.createTmp(); 63 final ImageEntry i1 = new ImageEntry(); 64 i1.setExifTime(DateUtils.fromString("2016:01:03 12:04:01")); 65 i1.createTmp(); 66 final ImageEntry i2 = new ImageEntry(); 67 i2.setExifTime(DateUtils.fromString("2016:01:03 12:04:57")); 68 i2.createTmp(); 69 final ImageEntry i3 = new ImageEntry(); 70 i3.setExifTime(DateUtils.fromString("2016:01:03 12:05:05")); 71 i3.createTmp(); 72 final ImageEntry i4 = new ImageEntry(); //Image close to two points with elevation, but without time 73 i4.setExifTime(DateUtils.fromString("2016:01:03 12:05:20")); 74 i4.createTmp(); 75 final ImageEntry i5 = new ImageEntry(); //between two tracks, closer to first 76 i5.setExifTime(DateUtils.fromString("2016:01:03 12:07:00")); 77 i5.createTmp(); 78 final ImageEntry i6 = new ImageEntry(); //between two tracks, closer to second (more than 1 minute from any track) 79 i6.setExifTime(DateUtils.fromString("2016:01:03 12:07:45")); 80 i6.createTmp(); 81 82 List<ImageEntry> images = Arrays.asList(ib, i0, i1, i2, i3, i4, i5, i6); 83 84 // TEST #1: default settings 85 // tag images within 2 minutes to tracks/segments, interpolate between segments only 86 assertEquals(7, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false)); 87 assertEquals(null, ib.getPos()); 88 assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), i0.getPos()); // start of track 89 assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos()); // exact match 90 assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos()); // exact match 91 assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2), i2.getPos()); // interpolated 92 assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897), i4.getPos()); // interpolated between points without timestamp 93 assertEquals(new CachedLatLon(47.19819249585271, 8.78536943346262), i5.getPos()); // tagged to last WP of first track, because closer and within 2 min (default setting) 94 assertEquals(new CachedLatLon(47.20138901844621, 8.774476982653141), i6.getPos()); // tagged to first WP of second track, because closer and within 2 min (default setting) 95 assertFalse(ib.hasNewGpsData()); 96 assertTrue(i0.hasNewGpsData() && i1.hasNewGpsData() && i2.hasNewGpsData() && i3.hasNewGpsData() 97 && i4.hasNewGpsData() && i5.hasNewGpsData() && i6.hasNewGpsData()); 98 // First waypoint has no speed in matchGpxTrack(). Speed is calculated 99 // and not taken from GPX track. 100 assertEquals(null, ib.getSpeed()); 101 assertEquals(null, i0.getSpeed()); 102 assertEquals(Double.valueOf(11.675317966018756), i1.getSpeed(), 0.000001); 103 assertEquals(Double.valueOf(24.992418392716967), i2.getSpeed(), 0.000001); 104 assertEquals(Double.valueOf(27.307968754679223), i3.getSpeed(), 0.000001); 105 assertEquals(null, ib.getElevation()); 106 assertEquals(null, i0.getElevation()); 107 assertEquals(Double.valueOf(489.29), i1.getElevation(), 0.000001); 108 assertEquals(Double.valueOf((490.40 + 489.75) / 2), i2.getElevation(), 0.000001); 109 assertEquals(Double.valueOf(486.368333333), i3.getElevation(), 0.000001); 110 assertEquals(Double.valueOf(475.393978719), i4.getElevation(), 0.000001); //interpolated elevation between trackpoints with interpolated timestamps 111 assertEquals(null, i5.getElevation()); 112 assertEquals(null, i6.getElevation()); 113 114 assertEquals(null, ib.getGpsTime()); 115 assertEquals(DateUtils.fromString("2016:01:03 11:59:54"), i0.getGpsTime()); // original time is kept 116 assertEquals(DateUtils.fromString("2016:01:03 12:04:01"), i1.getGpsTime()); 117 assertEquals(DateUtils.fromString("2016:01:03 12:04:57"), i2.getGpsTime()); 118 assertEquals(DateUtils.fromString("2016:01:03 12:05:05"), i3.getGpsTime()); 119 120 clearTmp(images); 121 122 // TEST #2: Disable all interpolation and tagging close to tracks. Only i1-i4 are tagged 123 124 s.putBoolean("geoimage.trk.tag", false); 125 s.putBoolean("geoimage.trk.int", false); 126 s.putBoolean("geoimage.seg.tag", false); 127 s.putBoolean("geoimage.seg.int", false); 128 129 assertEquals(4, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false)); 130 assertEquals(null, ib.getPos()); 131 assertEquals(null, i0.getPos()); 132 assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos()); 133 assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2), i2.getPos()); 134 assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos()); 135 assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897), i4.getPos()); 136 assertEquals(null, i5.getPos()); 137 assertEquals(null, i6.getPos()); 138 139 clearTmp(images); 140 141 // TEST #3: Disable all interpolation and allow tagging within 1 minute of a track. i0-i5 are tagged. 142 // i6 will not be tagged, because it's 68 seconds away from the next waypoint in either direction 143 144 s.putBoolean("geoimage.trk.tag", true); 145 s.putBoolean("geoimage.trk.tag.time", true); 146 s.putInt("geoimage.trk.tag.time.val", 1); 147 148 s.putBoolean("geoimage.trk.int", false); 149 s.putBoolean("geoimage.seg.tag", false); 150 s.putBoolean("geoimage.seg.int", false); 151 152 assertEquals(6, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false)); 153 assertEquals(null, ib.getPos()); 154 assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), i0.getPos()); 155 assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos()); 156 assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2), i2.getPos()); 157 assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos()); 158 assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897), i4.getPos()); 159 assertEquals(new CachedLatLon(47.19819249585271, 8.78536943346262), i5.getPos()); 160 assertEquals(null, i6.getPos()); 161 162 clearTmp(images); 163 164 // TEST #4: Force tagging (parameter forceTags=true, no change of configuration). All images will be tagged 165 // i5-i6 will now be interpolated, therefore it will have an elevation and different coordinates than in tests above 166 167 assertEquals(8, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, true)); 168 assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), ib.getPos()); 169 assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), i0.getPos()); 170 assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos()); 171 assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2), i2.getPos()); 172 assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos()); 173 assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897), i4.getPos()); 174 assertEquals(new CachedLatLon(47.198845306804905, 8.783144918860685), i5.getPos()); // interpolated between tracks 175 assertEquals(new CachedLatLon(47.19985828931693, 8.77969308585768), i6.getPos()); // different values than in tests #1 and #3! 176 177 assertEquals(Double.valueOf(447.894014085), i5.getElevation(), 0.000001); 178 assertEquals(Double.valueOf(437.395070423), i6.getElevation(), 0.000001); 179 180 clearTmp(images); 181 182 // TEST #5: Force tagging (parameter forceTags=false, but configuration changed). 183 // Results same as #4 184 185 s.putBoolean("geoimage.trk.tag", true); 186 s.putBoolean("geoimage.trk.tag.time", false); 187 s.putBoolean("geoimage.trk.int", true); 188 s.putBoolean("geoimage.trk.int.time", false); 189 s.putBoolean("geoimage.trk.int.dist", false); 190 s.putBoolean("geoimage.seg.tag", false); 191 s.putBoolean("geoimage.seg.int", false); 192 s.putBoolean("geoimage.seg.tag.time", false); 193 s.putBoolean("geoimage.seg.int", true); 194 s.putBoolean("geoimage.seg.int.time", false); 195 s.putBoolean("geoimage.seg.int.dist", false); 196 197 assertEquals(8, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false)); 198 assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), ib.getPos()); 199 assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), i0.getPos()); 200 assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos()); 201 assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2), i2.getPos()); 202 assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos()); 203 assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897), i4.getPos()); 204 assertEquals(new CachedLatLon(47.198845306804905, 8.783144918860685), i5.getPos()); 205 assertEquals(new CachedLatLon(47.19985828931693, 8.77969308585768), i6.getPos()); 206 207 assertEquals(Double.valueOf(447.894014085), i5.getElevation(), 0.000001); 208 assertEquals(Double.valueOf(437.395070423), i6.getElevation(), 0.000001); 209 210 clearTmp(images); 211 212 // TEST #6: Disable tagging but allow interpolation when tracks are less than 500m apart. i0-i4 are tagged. 213 // i5-i6 will not be tagged, because the tracks are 897m apart. 214 // not checking all the coordinates again, did that 5 times already, just the number of matched images 215 216 s.putBoolean("geoimage.trk.tag", false); 217 s.putBoolean("geoimage.trk.int", true); 218 s.putBoolean("geoimage.trk.int.time", false); 219 s.putBoolean("geoimage.trk.int.dist", true); 220 s.putInt("geoimage.trk.int.dist.val", 500); 221 s.putBoolean("geoimage.seg.tag", false); 222 s.putBoolean("geoimage.seg.int", false); 223 224 assertEquals(4, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false)); 225 clearTmp(images); 226 227 // TEST #7: Disable tagging but allow interpolation when tracks are less than 1000m apart. i0-i6 are tagged. 228 // i5-i6 will be tagged, because the tracks are 897m apart. 229 230 s.putInt("geoimage.trk.int.dist.val", 1000); 231 232 assertEquals(6, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false)); 233 clearTmp(images); 234 235 // TEST #8: Disable tagging but allow interpolation when tracks are less than 2 min apart. i0-i4 are tagged. 236 // i5-i6 will not be tagged, because the tracks are 2.5min apart. 237 238 s.putBoolean("geoimage.trk.tag", false); 239 s.putBoolean("geoimage.trk.int", true); 240 s.putBoolean("geoimage.trk.int.time", true); 241 s.putInt("geoimage.trk.int.time.val", 2); 242 s.putBoolean("geoimage.trk.int.dist", false); 243 s.putBoolean("geoimage.seg.tag", false); 244 s.putBoolean("geoimage.seg.int", false); 245 246 assertEquals(4, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false)); 247 clearTmp(images); 248 249 // TEST #9: Disable tagging but allow interpolation when tracks are less than 3 min apart. i0-i6 are tagged. 250 // i5-i6 will be tagged, because the tracks are 2.5min apart. 251 252 s.putInt("geoimage.trk.int.time.val", 3); 253 254 assertEquals(6, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false)); 255 256 } 257 258 private void clearTmp(List<ImageEntry> imgs) { 259 for (ImageEntry i : imgs) { 260 i.discardTmp(); 261 i.createTmp(); 262 } 263 } 264 } -
test/unit/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImagesTest.java
2 2 package org.openstreetmap.josm.gui.layer.geoimage; 3 3 4 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertFalse;6 import static org.junit.Assert.assertTrue;7 5 8 import java.util.Arrays;9 6 import java.util.Collections; 10 7 11 8 import org.junit.BeforeClass; 12 9 import org.junit.Rule; 13 10 import org.junit.Test; 14 import org.openstreetmap.josm.data.coor.CachedLatLon;15 11 import org.openstreetmap.josm.data.gpx.GpxData; 16 12 import org.openstreetmap.josm.io.GpxReaderTest; 17 13 import org.openstreetmap.josm.testutils.JOSMTestRules; … … 42 38 } 43 39 44 40 /** 45 * Tests matching of images to a GPX track.46 * @throws Exception if the track cannot be parsed47 */48 @Test49 public void testMatchGpxTrack() throws Exception {50 final GpxData gpx = GpxReaderTest.parseGpxData("data_nodist/2094047.gpx");51 assertEquals(4, gpx.tracks.size());52 assertEquals(1, gpx.tracks.iterator().next().getSegments().size());53 assertEquals(185, gpx.tracks.iterator().next().getSegments().iterator().next().getWayPoints().size());54 55 final ImageEntry ib = new ImageEntry();56 ib.setExifTime(DateUtils.fromString("2016:01:03 11:54:58")); // 5 minutes before start of GPX57 ib.createTmp();58 final ImageEntry i0 = new ImageEntry();59 i0.setExifTime(DateUtils.fromString("2016:01:03 11:59:54")); // 4 sec before start of GPX60 i0.createTmp();61 final ImageEntry i1 = new ImageEntry();62 i1.setExifTime(DateUtils.fromString("2016:01:03 12:04:01"));63 i1.createTmp();64 final ImageEntry i2 = new ImageEntry();65 i2.setExifTime(DateUtils.fromString("2016:01:03 12:04:57"));66 i2.createTmp();67 final ImageEntry i3 = new ImageEntry();68 i3.setExifTime(DateUtils.fromString("2016:01:03 12:05:05"));69 i3.createTmp();70 71 assertEquals(4, CorrelateGpxWithImages.matchGpxTrack(Arrays.asList(ib, i0, i1, i2, i3), gpx, 0));72 assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), i0.getPos()); // start of track73 assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos()); // exact match74 assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos()); // exact match75 assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2),76 i2.getPos()); // interpolated77 assertFalse(ib.hasNewGpsData());78 assertTrue(i0.hasNewGpsData());79 assertTrue(i1.hasNewGpsData());80 assertTrue(i2.hasNewGpsData());81 assertTrue(i3.hasNewGpsData());82 // First waypoint has no speed in matchGpxTrack(). Speed is calculated83 // and not taken from GPX track.84 assertEquals(null, ib.getSpeed());85 assertEquals(null, i0.getSpeed());86 assertEquals(Double.valueOf(11.675317966018756), i1.getSpeed(), 0.000001);87 assertEquals(Double.valueOf(24.992418392716967), i2.getSpeed(), 0.000001);88 assertEquals(Double.valueOf(27.307968754679223), i3.getSpeed(), 0.000001);89 assertEquals(null, ib.getElevation());90 assertEquals(Double.valueOf(471.86), i0.getElevation(), 0.000001);91 assertEquals(Double.valueOf(489.29), i1.getElevation(), 0.000001);92 assertEquals(Double.valueOf((490.40 + 489.75) / 2), i2.getElevation(), 0.000001);93 assertEquals(Double.valueOf(486.368333333), i3.getElevation(), 0.000001);94 assertEquals(null, ib.getGpsTime());95 assertEquals(DateUtils.fromString("2016:01:03 11:59:54"), i0.getGpsTime()); // original time is kept96 assertEquals(DateUtils.fromString("2016:01:03 12:04:01"), i1.getGpsTime());97 assertEquals(DateUtils.fromString("2016:01:03 12:04:57"), i2.getGpsTime());98 assertEquals(DateUtils.fromString("2016:01:03 12:05:05"), i3.getGpsTime());99 }100 101 /**102 41 * Tests automatic guessing of timezone/offset 103 42 * @throws Exception if an error occurs 104 43 */
