teecup/frontend/lib/geo.test.ts

69 lines
2.7 KiB
TypeScript
Raw Normal View History

import { describe, expect, it } from "vitest"
import { bearingDegrees, haversineMeters } from "./geo"
describe("haversineMeters", () => {
it("er 0 for identiske punkt", () => {
expect(haversineMeters({ lat: 59.9139, lng: 10.7522 }, { lat: 59.9139, lng: 10.7522 })).toBe(0)
})
it("matcher en kjent fasit -- Oslo til Bergen, ca. 305 km luftlinje", () => {
// Oslo sentrum og Bergen sentrum -- ekte koordinater, ekte kjent
// omtrentlig storsirkel-avstand (ikke kjøreavstand), ikke en oppdiktet
// verdi. Toleranse ±3 km for koordinat-presisjon.
const oslo = { lat: 59.9139, lng: 10.7522 }
const bergen = { lat: 60.3913, lng: 5.3221 }
const meters = haversineMeters(oslo, bergen)
expect(meters).toBeGreaterThan(302_000)
expect(meters).toBeLessThan(308_000)
})
it("1 breddegrad ved ekvator er ca. 111.2 km -- kjent geodetisk fasit", () => {
const meters = haversineMeters({ lat: 0, lng: 0 }, { lat: 1, lng: 0 })
expect(meters).toBeGreaterThan(110_500)
expect(meters).toBeLessThan(111_500)
})
it("er symmetrisk (a til b == b til a)", () => {
const a = { lat: 59.91, lng: 10.75 }
const b = { lat: 59.92, lng: 10.76 }
expect(haversineMeters(a, b)).toBeCloseTo(haversineMeters(b, a), 6)
})
it("golf-relevant kort avstand (typisk slaglengde, ca. 150 m) er presis", () => {
// 150 m nord for et fast punkt -- ren nord-sør-forskyvning, lett å
// regne ut fasit for: 150 m / 111 320 m per breddegrad.
const start = { lat: 59.9, lng: 10.75 }
const metersNorth = 150
const end = { lat: 59.9 + metersNorth / 111_320, lng: 10.75 }
expect(haversineMeters(start, end)).toBeCloseTo(metersNorth, 0)
})
})
describe("bearingDegrees", () => {
it("rett nord er 0 grader", () => {
expect(bearingDegrees({ lat: 59.9, lng: 10.75 }, { lat: 60.0, lng: 10.75 })).toBeCloseTo(0, 1)
})
it("rett øst er 90 grader", () => {
// På ekvator for å unngå meridiankonvergens-forvrengning ved høyere
// breddegrad -- en ren øst-forskyvning der er den enkleste fasiten.
expect(bearingDegrees({ lat: 0, lng: 10 }, { lat: 0, lng: 10.1 })).toBeCloseTo(90, 1)
})
it("rett sør er 180 grader", () => {
expect(bearingDegrees({ lat: 59.9, lng: 10.75 }, { lat: 59.8, lng: 10.75 })).toBeCloseTo(180, 1)
})
it("rett vest er 270 grader", () => {
expect(bearingDegrees({ lat: 0, lng: 10 }, { lat: 0, lng: 9.9 })).toBeCloseTo(270, 1)
})
it("returnerer alltid en verdi i [0, 360)", () => {
const a = { lat: 59.91, lng: 10.75 }
const b = { lat: 59.85, lng: 10.6 }
const bearing = bearingDegrees(a, b)
expect(bearing).toBeGreaterThanOrEqual(0)
expect(bearing).toBeLessThan(360)
})
})