fix: Punkte ohne Koordinaten, Fehlertext, neuer Test für Null-Island
- Prüfe lat/lon auf null vor Number-Konvertierung (Number(null) ist 0, nicht NaN) - Ergänze Test für übersprungene Punkte ohne Koordinaten - Bessere Fehlermeldung für ungültiges XML Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ef8c05bd7c
commit
f89f163e22
2 changed files with 25 additions and 4 deletions
|
|
@ -99,6 +99,20 @@ describe('parseGpx', () => {
|
||||||
expect(parseGpx(route).points).toHaveLength(2)
|
expect(parseGpx(route).points).toHaveLength(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('überspringt Punkte ohne lat/lon statt sie auf 0,0 zu setzen', () => {
|
||||||
|
const broken = `<?xml version="1.0"?>
|
||||||
|
<gpx version="1.1" xmlns="http://www.topografix.com/GPX/1/1"><trk><trkseg>
|
||||||
|
<trkpt lat="49.510" lon="11.430"><ele>300</ele></trkpt>
|
||||||
|
<trkpt><ele>310</ele></trkpt>
|
||||||
|
<trkpt lat="49.512" lon="11.432"><ele>320</ele></trkpt>
|
||||||
|
</trkseg></trk></gpx>`
|
||||||
|
const r = parseGpx(broken)
|
||||||
|
expect(r.points).toHaveLength(2)
|
||||||
|
// Ohne die Prüfung reichte die Bounding-Box bis 0/0
|
||||||
|
expect(r.bounds[0][0]).toBeGreaterThan(11)
|
||||||
|
expect(r.distance_m).toBeLessThan(1000)
|
||||||
|
})
|
||||||
|
|
||||||
it('wirft bei einer Datei ohne Punkte', () => {
|
it('wirft bei einer Datei ohne Punkte', () => {
|
||||||
const empty = `<?xml version="1.0"?>
|
const empty = `<?xml version="1.0"?>
|
||||||
<gpx version="1.1" xmlns="http://www.topografix.com/GPX/1/1"></gpx>`
|
<gpx version="1.1" xmlns="http://www.topografix.com/GPX/1/1"></gpx>`
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ export function parseGpx(xml: string): ParsedGpx {
|
||||||
const doc = new DOMParser().parseFromString(xml, 'application/xml')
|
const doc = new DOMParser().parseFromString(xml, 'application/xml')
|
||||||
|
|
||||||
if (doc.querySelector('parsererror')) {
|
if (doc.querySelector('parsererror')) {
|
||||||
throw new Error('Die Datei ist ungültig.')
|
throw new Error('Die GPX-Datei ist ungültig.')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manche Programme exportieren Routen (rtept) statt Tracks (trkpt).
|
// Manche Programme exportieren Routen (rtept) statt Tracks (trkpt).
|
||||||
|
|
@ -130,8 +130,15 @@ export function parseGpx(xml: string): ParsedGpx {
|
||||||
|
|
||||||
const points: TrackPoint[] = []
|
const points: TrackPoint[] = []
|
||||||
for (const n of nodes) {
|
for (const n of nodes) {
|
||||||
const lat = Number(n.getAttribute('lat'))
|
const latAttr = n.getAttribute('lat')
|
||||||
const lng = Number(n.getAttribute('lon'))
|
const lngAttr = n.getAttribute('lon')
|
||||||
|
// Number(null) ist 0, nicht NaN — ohne diese Prüfung landen Punkte
|
||||||
|
// ohne Koordinaten bei 0/0 im Golf von Guinea und verfälschen
|
||||||
|
// Streckenlänge und Bounding-Box.
|
||||||
|
if (latAttr === null || lngAttr === null) continue
|
||||||
|
|
||||||
|
const lat = Number(latAttr)
|
||||||
|
const lng = Number(lngAttr)
|
||||||
if (!Number.isFinite(lat) || !Number.isFinite(lng)) continue
|
if (!Number.isFinite(lat) || !Number.isFinite(lng)) continue
|
||||||
|
|
||||||
const eleText = n.getElementsByTagName('ele')[0]?.textContent
|
const eleText = n.getElementsByTagName('ele')[0]?.textContent
|
||||||
|
|
@ -171,7 +178,7 @@ export function parseGpx(xml: string): ParsedGpx {
|
||||||
// Abstieg über Schwelle: neuer Bezugspunkt, aber nicht gezählt
|
// Abstieg über Schwelle: neuer Bezugspunkt, aber nicht gezählt
|
||||||
lastCountedEle = ele
|
lastCountedEle = ele
|
||||||
}
|
}
|
||||||
// Kleine Schwankungen (-3...+3) ignorieren, Bezugspunkt bleibt
|
// Kleine Schwankungen (unter 3 m) ignorieren, Bezugspunkt bleibt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue